运算符重载问题

3
目前我正在尝试为我编写的名为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&)

有人知道我该如何更改我的代码才能实现这个功能吗?

你能发布MyString类的完整源代码吗? - Ternary
1
这个功能没有任何意义。你想在同一语句中使用多个 += 是什么意思?那会改变运算符的语义。 - danca
加号运算符不能只是像这样的东西吗?“返回 s1 + s2” - hookenz
在函数中添加打印语句以查看发生的顺序。此语句执行后,每个变量的内容是什么? - Seth Carnegie
1
如果你询问一个问题,应该在你的问题中真正包含该问题的描述。"不起作用"是最糟糕的问题描述。如果你不说出出了什么问题,你怎么能期望别人能够帮助你呢? - sth
显示剩余3条评论
2个回答

3

在这种情况下,混合使用++=是没有意义的。我不确定您想要的行为是什么,但如果您希望嵌套的+=应用于test1,则必须使用括号:

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

这并不是你的赋值运算符的问题,而是语言中运算符优先级的问题。如果你将 MyString 替换为 int,你会遇到相同的问题。 ++= 运算符的优先级和结合性会导致没有括号的表达式被解释为以下内容:
test += ((test2 + test1) += "you");

这里试图将值赋给test2 + test1,但这是不可能的(你只能将值赋给变量)。这个运算符优先级不能被改变,如果没有使用括号,表达式将会被这种方式解释。

你能详细解释一下运算符优先级是如何导致我没有使用括号就无法编译的吗?我尝试了你的方法,确实可以使其工作。有没有办法在不使用括号的情况下让它工作呢? - KWJ2104
回应您的评论,很抱歉我之前没有在原帖中更加具体,但是我已经在一段时间前编辑了编译错误信息。 - KWJ2104

0

你的错误在这里:

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

程序将从'test2 + test1'创建临时对象,并调用其operator+=()。问题在于,一个表达式中有2个operator +=调用,不确定哪一个会先被调用。因此,operator+=(TemporaryObject,MyString("you"))的结果可能会丢失。
为了防止这种情况,您应该像这样声明operator+:
const MyString operator+(const MyString& s1, const MyString& s2)

如果你这样做,编译器将能够在遇到具有不可预测结果的表达式时发出错误信号;

编辑:

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

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

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


但是如果它们具有相同的优先级,那么运算符不是按照它们出现的顺序调用吗?例如,如果调用test1 + test2 + test3或类似的内容,为什么这不会出错?难道它不必判断哪个+应该首先被调用吗?我可能真的很困惑。此外,我尝试添加const,但我的代码仍无法编译并显示相同的错误。 - KWJ2104
根据Stroustrup的《C++程序设计语言》,“表达式中子表达式的求值顺序是未定义的”。无法参考标准。 - Pavel Zhuravlev
小提示:您不应该搞混优先级、结合性和评估顺序。这里有一个很好的解释:[链接](https://dev59.com/nOo6XIcBkEYKwwoYTSsu) - Pavel Zhuravlev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接