如何将此 VC++ 6 代码转换为 VC++ 2008?

Posted

技术标签:

【中文标题】如何将此 VC++ 6 代码转换为 VC++ 2008?【英文标题】:How to convert this VC++ 6 code to VC++ 2008? 【发布时间】:2009-04-11 17:06:23 【问题描述】:

请原谅我的 C++ 生锈得令人难以置信。但我正在尝试获取一些旧代码并在 Visual C++ 2008 下重新编译它。它最初是为 Visual C++ 6.0 编写的

我得到的错误是这样的:

错误 C4430:缺少类型说明符 - 假定为 int。注意:C++ 不支持 default-int

好的,看起来很简单。但后来我看看有问题的代码行:

operator=(int i) SetAsInt(i);;

它似乎声明了类型。那我错过了什么?

跟进:

我接受了 Micheals 的建议并添加了函数(类)的返回类型,并在每个末尾添加了 return this;。然后我遇到了这个:

operator=(const CString& str);

没有定义函数体...这到底是什么意思?

【问题讨论】:

请注意,返回对象的引用而不是对象的指针可能应该是return *this;。或者,您可以通过声明返回 void 的方法,正如 Neil Butterworth 所建议的那样,您可能无法获得分配链支持(通常可以忽略不计)。 【参考方案1】:

您需要让operator=() 方法返回一些内容(如果诊断不是错误,它将假定为 int,因为错误消息有些令人困惑)。

通常它是对运算符正在处理的对象的引用,因此可以像在正常的赋值表达式中一样链接赋值。比如:

// where T is the class for this operator= implementation

T& operator=( int i) 
     // ...
    return *this;

【讨论】:

最好使用 const,即:T const &operator=(int i) 它可以返回一个 const&,但通常不会。 operator=() 不是一个 const 方法(除非你正在做一些真正的事情),所以它没有什么理由返回一个 const&。并且返回一个 const& 会阻止经典(尽管不一定广泛使用)a = b = c; 链接。 “返回一个 const& 可以防止经典的(虽然不一定广泛使用)a = b = c; 链接。”不完全是,复制构造函数是从 const 引用创建的,因此赋值运算符具有签名 T const &operator=(T const &) 并且它以上述方式工作。 @Artyom:关于我返回 const& 防止赋值链接的错误,你是对的(虽然不是因为复制构造函数 - 这是因为 = 的关联性意味着 const& 结果是赋值的操作数,而不是目标)。 @Artyom:我看到的关于 operator=() 的通常建议是返回一个 T& - 在这次交换之后,我将开始考虑使用 T const& 除非我能想到一个好的const 应该被忽略的原因 - 或者其他人是否可以教育我。感谢您说服我重新考虑这一点。【参考方案2】:

正如 michael 所说,operator= 需要一个返回类型,但这种类型可以是 void:

class A 
   ...  
   void operator = ( int i ) 
      SetAsInt(i);
   
;

虽然这意味着您将无法“菊花链式”分配。

关于后续,可能是说禁止给班级分配:

class B 
    private:
        void operator =( const B & );    
;

将分配操作(通常是复制ctor)设为私有然后不实现它们意味着不可能分配(或复制)类实例,这是大多数面向业务的类的理想行为。

【讨论】:

【参考方案3】:

对于你的第二个问题,声明很可能被用来防止复制对象。

来自the C++ Reference Guide by Danny Kalev

问题:我该如何预防 对象复制?

答案:声明复制构造函数 并且赋值运算符是私有的 成员,而不定义它们。任何 涉及直接或 该类的间接复制将 导致编译错误。这 技术并不完全是 优雅,但在当代 C++ 中 没有其他方法可以阻止复制 便宜。

【讨论】:

好的,这对它有所启发。在我的 C++ 大学时代,他们从未提到过这一点。【参考方案4】:

关于您的编辑: 它只是意味着该函数已被声明,但未定义。编译器知道它存在,所以调用它是合法的。但它会产生链接器错误,除非编译器实际上能够在某处找到正文。

通常,你在头文件中定义函数,然后在 .cpp 文件中,你有类似的东西

// Assuming the class it is a member of is called Foo
Foo& Foo::operator=(const CString& str) 
 ...

这里唯一需要注意的是 Foo:: 前缀。因为这个定义在类定义本身之外,所以我们必须使用这个前缀来指定我们正在定义的 operator= 属于 Foo 类。

【讨论】:

好的,我找到了函数体。虽然我从不明白为什么 C++ 有这种奇怪的想法,即在一个地方声明,在另一个地方定义。 抓得好,贾夫。我从来没有想过要讨论这个解释,因为它是大多数 C++ 方法的定义方式。但是,我同意 Neil 的观点,声明/定义(如 Java/C#)只有一个位置更直观。 因为这样您可以#include 仅包含声明的文件,并且您可以调用该函数,而无需编译器再次解析整个函数体。在 70 年代,当设计 C 时,这是一种加快编译时间的简单方法。 30-40 年前,编译器无法证明像 Java/C# 编译器那样将整个文件保存在内存中的成本是合理的。它必须按顺序扫描文件,所以事情必须保持简单。今天,它是一种笨拙、容易出错且效率低下的机制。但在当时是有道理的。 ;)【参考方案5】:

返回 ANYTHING 但 lval 通常是错误的,仅在非常特殊的情况下使用

返回一个 const 引用肯定会排除赋值链 (a=(b=c)),而运算符的部分意义在于使类的行为类似于内置类型

【讨论】:

【参考方案6】:

嗯,这是一个赋值运算符。它有助于定义如何将其他对象(相同类型和其他类型)分配给定义它的类的实例。

正确的语法是(假设你的类叫做'Object'):

const Object& operator=(const Object& other)

  // copy members, one at a time.
  this->member1 = other.member1;
  return *this;

注意返回类型是常量。这是为了避免语义不正确、语法正确的语句,例如:

Object A, B, C;

(A = B) = C;

如果将返回类型定义为常量,上面的代码将无法编译(足够合理,因为它真的很乱),而省略 const 将允许这样糟糕的代码编译,当然有人会拉扯他们的头发尝试找出问题所在。

附:您可能需要考虑一下:如果您从返回类型中省略 const 并执行 (A = B) = C; 会发生什么?代码?

【讨论】:

【参考方案7】:

关于后续问题,在这种情况下,返回类型可以是任何东西。但是,由于大多数赋值运算符都返回对声明它们的类的引用,因此最好只返回该引用,以免使读者感到困惑。

CString& operator=(const CString& str);

大概,这个函数是在类的private 部分中声明的。这是使类的对象不可赋值的标准习惯用法。

【讨论】:

以上是关于如何将此 VC++ 6 代码转换为 VC++ 2008?的主要内容,如果未能解决你的问题,请参考以下文章

在 VC++ 中将 TCHAR 转换为 LPWSTR?

如何将 VC++6.0 项目升级到 VS2010?

vc 6.0 如何将数字转换成 字符串

如何将基于mpir库的VC9.0代码转换为Matlab mex函数?

VC++6.0 如何获取窗口客户区域在屏幕中的位置

wcstof 添加了哪个版本的VC++