【问题标题】:Operator Overloading Issue运算符重载问题
【发布时间】:2011-12-08 02:38:10
【问题描述】:

目前我正在尝试为我编写的名为 mystring 的类重写 += 运算符:

MyString& operator+=(MyString& s1, const MyString& s2)
{

    int newStringLength = s1.length + s2.length;
    char* newStorage = new char[newStringLength +  1];

    strcpy(newStorage, s1.data);

    strcpy(newStorage + s1.length, s2.data);
    delete[] s1.data;

    s1.length = newStringLength;
    s1.data = newStorage;

    return s1;

}

MyString operator+(const MyString& s1, const MyString& s2)
{

    MyString temp;
    delete[] temp.data;

    temp.length = s1.length;
    temp.data = new char[temp.length+1];

    strcpy(temp.data, s1.data);
    temp+=s2;

    return temp;

}

其中length是字符串的长度,data是以char *格式存储的字符串。

当我尝试执行以下操作时,程序运行良好:

MyString test1 = "hi";
MyString test2 = "to"; 

test1 += test2;

但是当我尝试以下方法时不起作用:

   MyString test;
    MyString test1 = "hi";
    MyString test2 = "to"; 

    test += test2 + test1
          += "you";

基本上,当我开始以交替方式混合 += 和 + 时,它不起作用。这是编译时的错误:

testoutput.cpp:26: error: no match for ‘operator+=’ in ‘operator+(const MyString&, const MyString&)(((const MyString&)((const MyString*)(& test1)))) += "you"’
mystring.h:45: note: candidates are: MyString& operator+=(MyString&, const MyString&)

有谁知道如何更改我的代码以实现此功能?

【问题讨论】:

  • s1.data 在默认构造函数中初始化为什么(您使用MyString test; 调用的内容是什么?
  • 数据=新字符[1];数据[0] = '\0';长度 = 0;
  • 你能发布 MyString 类的完整源代码吗?
  • 这个功能没有意义。您希望多个 += 在同一语句中表示什么?这改变了运算符的语义。
  • 如果询问某个问题,您应该在问题中包含对该问题的描述。 “不起作用”是最糟糕的问题描述。如果你不说哪里出了问题,你怎么指望有人能够提供帮助?

标签: c++ operator-overloading


【解决方案1】:

以这种方式混合++= 是没有意义的。我不太确定您的预期行为是什么,但如果您希望嵌套的 += 应用于 test1,则必须使用括号:

test += test2 + (test1 += "you");

这不是您的赋值运算符的问题,而是语言中的运算符优先级问题。如果您将MyString 替换为int,您会遇到同样的问题。

++= 运算符的 precedence and associativity 导致不带括号的表达式被解释为:

test += ((test2 + test1) += "you");

这会尝试分配给test2 + test1,但这是不可能的(您只能分配给变量)。此运算符优先级无法更改,并且如果没有括号,表达式将始终以这种方式解释。

【讨论】:

  • 你能解释一下运算符优先级是如何导致我没有括号就无法编译的吗?我试过你的方法,它确实使它工作。有没有办法让它在没有括号的情况下工作?
  • 另外,为了回应您对 OP 没有更具体的评论,我在不久前的帖子中编辑了关于编译的错误消息。
【解决方案2】:

你的错误在这里:

test += test2 + test1 += "you";

程序将从'test2 + test1'创建临时对象,并为它调用operator+=()。问题是,一个表达式中有 2 个运算符 += 调用,并且未定义首先调用哪个运算符。所以operator+=(TemporaryObject,MyString("you"))的结果可能会丢失;

为了防止这种情况,你应该像这样声明 operator+:

const MyString operator+(const MyString& s1, const MyString& s2)

如果您这样做,编译器将能够在偶然发现具有不可预测结果的此类表达式时发出错误信号;

编辑:

现在我们有了编译器输出,我看到编译器足够聪明,可以看到从 operator+() 创建的对象是临时的。所以,你只需要制作 2 个表达式而不是 1 个:

test += test2 + test1;
test += "you";

但我仍然建议从您的 operator+() 中返回 const 对象;

【讨论】:

  • 但是如果运算符具有相同的优先级,它们不只是按照它们出现的顺序调用吗?例如,如果调用 test1 + test2 + test3 或其他东西,为什么这不会搞砸,不是必须判断应该先调用哪个 + 吗?我可能真的很困惑。我也尝试添加 const 但我的代码仍然无法编译并给出相同的错误。
  • 根据 Stroustrup 的“C++ 编程语言”“表达式中子表达式的求值顺序未定义”。无法参考标准
  • 小补充:你不应该搞乱优先级、关联性和评估顺序。这里给出了一个很好的解释:link
猜你喜欢
  • 1970-01-01
  • 2014-04-14
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-22
相关资源
最近更新 更多