如何将此 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?的主要内容,如果未能解决你的问题,请参考以下文章