关于运算符重载

Victor_Dinho 2009-08-19 11:09:52
先贴程序
#include <iostream>
using namespace std;

class Test
{
public:
Test(int i = 0)
{
this->i = i;
}
Test& operator =(Test& t)
{
i = t.i;
return *this;
}
friend Test& operator +(Test& t1, Test& t2)
{
Test t;
t.i = t1.i + t2.i;
return t;
}
int i;
};

int main()
{
Test t1(1), t2(2), t3;
t3 = t1 + t2;
cout<<t3.i<<'\n';
return 0;
}


程序那里,friend Test& operator +(Test& t1, Test& t2)这个函数,我是返回引用值,但那个引用值所引用的变量是在函数中定义的,这应该是不对的,编译的时候也有一个warning出现。

我就想问一下如果要返回引用,在重载+号的时候应该怎么做呢?谢谢~
...全文
193 45 打赏 收藏 转发到动态 举报
写回复
用AI写文章
45 条回复
切换为时间正序
请发表友善的回复…
发表回复
zgjxwl 2009-08-19
  • 打赏
  • 举报
回复
别把+的语义改变了。。+本身就应该返回非引用。。不返回引用会返回一个临时对象。才符合+的语义。
Victor_Dinho 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 xingzhe2001 的回复:]
所以,写一个必须返回一个新对象的函数的正确方法就是让这个函数返回一个新对象。对于rational的operator*来说,这意味着要不就是下面的代码(就是最初看到的那段代码),要不就是本质上和它等价的代码:

C/C++ codeinlineconst rationaloperator*(const rational& lhs,const rational& rhs)
{return rational(lhs.n* rhs.n, lhs.d* rhs.d);
}

的确,这会导致“operator*的返回值构造和析构时带来的开销”,但归根结底它只是用小的代价换来正确的程序运行行为而已。况且,你所担心的开销还有可能永远不会出现:和所有程序设计语言一样,c++允许编译器的设计者采用一些优化措施来提高所生成的代码的性能,所以,在有些场合,operator*的返回值会被安全地除去(见条款m20)。当编译器采用了这种优化时(当前大部分编译器这么做),程序和以前一样继续工作,只不过是运行速度比你预计的要快而已。

以上讨论可以归结为:当需要在返回引用和返回对象间做决定时,你的职责是选择可以完成正确功能的那个。至于怎么让这个选择所产生的代价尽可能的小,那是编译器的生产商去想的事。

摘自《Effective C++ 》

[/Quote]

恩~~明白了~~~谢谢

现在我是像你说的那样做了,但又有一个问题:我在刚才重载+的函数中改了一下:
    friend Test operator +(const Test& t1, const Test& t2)
{
Test t;
t.setI(t1.getI() + t2.getI());
return t;
}

会报告错误:
C:\Documents and Settings\clerk\My Documents\test.cpp|27|error: passing `const Test' as `this' argument of `int Test::getI()' discards qualifiers|
难道设置成const之后就不能调用成员函数了吗?
xingzhe2001 2009-08-19
  • 打赏
  • 举报
回复
所以,写一个必须返回一个新对象的函数的正确方法就是让这个函数返回一个新对象。对于rational的operator*来说,这意味着要不就是下面的代码(就是最初看到的那段代码),要不就是本质上和它等价的代码:

inline const rational operator*(const rational& lhs,
const rational& rhs)
{
return rational(lhs.n * rhs.n, lhs.d * rhs.d);
}


的确,这会导致“operator*的返回值构造和析构时带来的开销”,但归根结底它只是用小的代价换来正确的程序运行行为而已。况且,你所担心的开销还有可能永远不会出现:和所有程序设计语言一样,c++允许编译器的设计者采用一些优化措施来提高所生成的代码的性能,所以,在有些场合,operator*的返回值会被安全地除去(见条款m20)。当编译器采用了这种优化时(当前大部分编译器这么做),程序和以前一样继续工作,只不过是运行速度比你预计的要快而已。

以上讨论可以归结为:当需要在返回引用和返回对象间做决定时,你的职责是选择可以完成正确功能的那个。至于怎么让这个选择所产生的代价尽可能的小,那是编译器的生产商去想的事。

摘自《Effective C++ 》

xingzhe2001 2009-08-19
  • 打赏
  • 举报
回复
条款23: 必须返回一个对象时不要试图返回一个引用
xingzhe2001 2009-08-19
  • 打赏
  • 举报
回复
《Effective C++ 》有对这个问题的讨论,最好这样返回了。
Victor_Dinho 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 xingzhe2001 的回复:]
引用 19 楼 victor_dinho 的回复:
引用 18 楼 xingzhe2001 的回复:
引用 15 楼 victor_dinho 的回复:
但是一般来说,假如那个类比较大,用引用的效率会比较高~~~不知道有没有更好的方法~~


重新设计你的软件,类比较大的时候真的需要重载+操作符?


我在自己写一个高精度整数的类,肯定要重载+操作符的~~


我说是" 类比较大的时候",
[/Quote]

其实……如果我真的想这样用,就没有可以work的方法了吗?
xingzhe2001 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 victor_dinho 的回复:]
引用 18 楼 xingzhe2001 的回复:
引用 15 楼 victor_dinho 的回复:
但是一般来说,假如那个类比较大,用引用的效率会比较高~~~不知道有没有更好的方法~~


重新设计你的软件,类比较大的时候真的需要重载+操作符?


我在自己写一个高精度整数的类,肯定要重载+操作符的~~
[/Quote]

我说是" 类比较大的时候",
xingzhe2001 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 victor_dinho 的回复:]
引用 18 楼 xingzhe2001 的回复:
引用 15 楼 victor_dinho 的回复:
但是一般来说,假如那个类比较大,用引用的效率会比较高~~~不知道有没有更好的方法~~


重新设计你的软件,类比较大的时候真的需要重载+操作符?


我在自己写一个高精度整数的类,肯定要重载+操作符的~~
[/Quote]

高精度整数能占多大空间??
Victor_Dinho 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 fly___fly 的回复:]
引用 10 楼 victor_dinho 的回复:
而且如果返回值不是引用,那么例如t3 = t1 + t2 + t3;之类的连续相加就不能用了。


这种说法是毫无道理的。。
operater +() 返回 Test而不是Test&时, t1 + t2 得到的是一个Test,再去加t3,没有任何问题。
[/Quote]

开始的时候的确是有问题,现在我对t1和t2加上const上去,就可以了~~~
zzandyc 2009-08-19
  • 打赏
  • 举报
回复
+操作符应直接返回对象,不应返回引用
Victor_Dinho 2009-08-19
  • 打赏
  • 举报
回复
后来又改了一下,好像OK了~~
#include <iostream>
using namespace std;

class Test
{
public:
Test(int i = 0)
{
this->i = i;
}
Test& operator =(const Test& t)
{
i = t.i;
return *this;
}
friend Test operator +(const Test& t1, const Test& t2)
{
Test t;
t.i = t1.i + t2.i;
return t;
}
int i;
};

int main()
{
Test t1(1), t2(2), t3(2);
t3 = t1 + t2 + t3;
cout<<t3.i<<'\n';
return 0;
}


不知道还有没有问题~~
fly___fly 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 victor_dinho 的回复:]
而且如果返回值不是引用,那么例如t3 = t1 + t2 + t3;之类的连续相加就不能用了。
[/Quote]

这种说法是毫无道理的。。
operater +() 返回 Test而不是Test&时, t1 + t2 得到的是一个Test,再去加t3,没有任何问题。
Victor_Dinho 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 xingzhe2001 的回复:]
引用 15 楼 victor_dinho 的回复:
但是一般来说,假如那个类比较大,用引用的效率会比较高~~~不知道有没有更好的方法~~


重新设计你的软件,类比较大的时候真的需要重载+操作符?
[/Quote]

我在自己写一个高精度整数的类,肯定要重载+操作符的~~
xingzhe2001 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 victor_dinho 的回复:]
但是一般来说,假如那个类比较大,用引用的效率会比较高~~~不知道有没有更好的方法~~
[/Quote]

重新设计你的软件,类比较大的时候真的需要重载+操作符?
xinshou2595 2009-08-19
  • 打赏
  • 举报
回复


Test&operator=(Test& t)
{
i= t.i;return*this;
}

说实话 我个人感觉 这个一点用也没有
Victor_Dinho 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 xinshou2595 的回复:]
C/C++ code
Test&operator+(Test& t1, Test& t2)
{
t1.i+= t2.i;return t1;

}
这样就可以的
[/Quote]

这样是不行的,程序会把t1得值都改变了~~
Victor_Dinho 2009-08-19
  • 打赏
  • 举报
回复
我后来改成了完全不用引用的程序,是完全没问题的。
#include <iostream>
using namespace std;

class Test
{
public:
Test(int i = 0)
{
this->i = i;
}
Test operator =(Test t)
{
i = t.i;
return *this;
}
friend Test operator +(Test t1, Test t2)
{
Test t;
t.i = t1.i + t2.i;
return t;
}
int i;
};

int main()
{
Test t1(1), t2(2), t3(2);
t3 = t1 + t2 + t3;
cout<<t3.i<<'\n';
return 0;
}


但是一般来说,假如那个类比较大,用引用的效率会比较高~~~不知道有没有更好的方法~~
xinshou2595 2009-08-19
  • 打赏
  • 举报
回复

Test& operator +(Test& t1, Test& t2)
{
t1.i += t2.i;
return t1;

}


这样就可以的
xingzhe2001 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 cfz379945430 的回复:]
引用 3 楼 liao05050075 的回复:
C/C++ code
friend Test&operator+(Test& t1, Test& t2)
    {
        t1.i+= t2.i;return t1;
    }
这样行不?



[/Quote]
比如

class CInt;
CInt A(2), B(1), C;
C = A + B;
//你会发现:
//C=3,A=3 不符合惯例
Victor_Dinho 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 xinshou2595 的回复:]
重载+号没有问题吧~~~ 你那个
C/C++ code
Test&operator=(Test& t)
{
i= t.i;return*this;
}
做什么的? 没有用吧?
[/Quote]

这个是简单地赋值啊~~
加载更多回复(25)

64,439

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧