【问题标题】:operator overloading运算符重载
【发布时间】:2011-04-08 01:27:06
【问题描述】:

我创建了一个 myString 类,我正在尝试运行以下代码:

class myString{
    char* str;
    int len;

public:
    myString(char* str1 = " "){
        len = strlen(str1);
        str = new char[len+1];
        strcpy(str, str1);
    };

    int getLen() const {
        return len;
    };

    char* getString() const {
        return str;
    };

    ~myString(){
        delete[] str;
    };

    myString& operator=(myString& orig){
        cout << "hello";
        if (str == NULL){
            delete[] str;
        };
        str = new char[orig.getLen()];
        strcpy(str, orig.getString());
        cout << this << endl;
        return *this;
    };

    ...
};



int main(){


    myString s("bla");
    myString k("dingo");
        myString g = s;
        // s=k;  //When this line is commented I get a linking error
         ...
   };

我的问题:

  1. 为什么不打印“hello”?
  2. 为什么s=k 行会导致链接器错误?

这是错误:

链接:c:\users\perry\documents\visual studio 2010\Projects\inheritance\Debug\inheritance.exe 未找到或未构建 通过最后一个增量链接;执行完整链接 1>main.obj:错误 LNK2019:未解析的外部符号“类 std::basic_ostream > & __cdecl 运算符

&,class myString *)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@PAVmyString@@@Z) 在函数“public: class myString & __thiscall”中引用 myString::operator=(class myString &)" (??4myString@@QAEAAV0@AAV0@@Z) 1>c:\用户\佩里\文档\视觉工作室 2010\Projects\inheritance\Debug\inheritance.exe:致命错误 LNK1120: 1 个未解决的外部问题

谢谢, 李

【问题讨论】:

  • 我已添加错误消息。感谢您的帮助:)
  • 你需要查找三的规则(或者是四)。无论如何,需要一个正确的赋值运算符和复制构造函数(缺少复制构造函数,并且赋值运算符声明不是我所说的标准(并且实现是错误的(在 len 中有一个错误)))。当您使用它时,请查找副本并交换 idium。

标签: c++ operator-overloading operator-keyword


【解决方案1】:

对于以下内容,您需要一个复制构造函数。它不使用赋值运算符功能。

myString g = s;

编辑

对于链接器错误 - 我无法帮助您。与其猜测operator&lt;&lt; 该行调用了什么,我将放弃这一点,因为您尚未提供代码。在普通的 C++ 代码中,简单的cout &lt;&lt; this; 不会导致链接器错误。 cout 有一个接受 void const* 的运算符。您在某处声明了一个提供更好匹配但未定义它的运算符。

【讨论】:

  • @pm100 生成一个默认值
  • 谢谢。我将添加复制构造函数。关于链接错误的任何想法?
  • 那么当 g = s 执行时会发生什么?为什么编译器对 s=k 的处理方式不同?
【解决方案2】:

链接错误是你没有定义

operator<<(class std::basic_ostream< >  &,class myString *)

由于线路

cout << this << endl;

【讨论】:

  • 有趣的是它可以编译但无法链接。我原以为它会编译失败
  • 不确定它是否只是MSVC,但它通常会首先使用一个未知的方法作为默认定义,这可以隐藏使用未定义的东西的编译问题。
【解决方案3】:

我觉得应该是的

operator=(const myString &orig)

【讨论】:

    【解决方案4】:
    myString g = s;
    

    这不调用operator=,而是复制构造函数。由于您尚未定义任何复制构造函数,因此会生成一个默认构造函数,复制所有字段。但是你拿着指针,你不希望这种情况发生!这就是为什么你需要一个复制构造函数。

    关于链接错误:

    cout << this << endl;
    

    在这里,您尝试使用operator&lt;&lt;。 this 的类型是myString*,未定义此运算符。如果要打印 this 指针的值,可以转换一下:

    cout << (void*) this << endl;
    



     if (str == NULL){
                    delete[] str;
                };
    

    你想在这里if (str != NULL)(错字?)。

    【讨论】:

    • 哇哦!!!谢谢,那(无效*)拯救了我的夜晚。非常感谢您。出于某种原因,当我看到那些链接错误时,我吓坏了。我必须开始更仔细地阅读它们。谢谢!!!
    • 顺便说一下,NULL检查是不必要的。 delete NULLdelete[] NULL 定义明确且合法。什么都没发生。而且您不需要在功能块或条件(if)块的末尾使用分号 - 仅在类和结构定义之后(当然还有语句!)
    【解决方案5】:

    首先,myString g = s; 是一个新的myString 的初始化,这是通过复制构造函数完成的(它是自动提供的,因为您没有编写它)。

    链接错误是因为cout &lt;&lt; this &lt;&lt; endl;这行,因为你没有告诉系统如何打印this,它显然想不出办法。

    在 C++ 中,存在三法则:如果您编写复制构造函数、赋值运算符或析构函数,您可能需要编写全部三个。 (例外情况是为基类编写虚拟析构函数。)通常,您的类管理一些资源(在您的情况下为str),您需要在所有三种情况下处理它。

    此外,尽可能使用const。您可以将非const 变量传递给const 引用,但反之则不行。

    你的析构函数很好。你的赋值运算符应该有签名myString &amp; operator=(const &amp;myString),你的复制构造函数应该有签名myString::myString(const &amp;myString)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-19
      • 1970-01-01
      • 2011-06-21
      • 2012-09-14
      • 2012-03-10
      • 2011-08-06
      相关资源
      最近更新 更多