函数返回值是一个类对象时,有以下几种选择:
1,返回对象或者对象的引用 2,它们是const的or not
1,返回对象的const引用,举例:
#include <iostream>
#include <cmath>
using namespace std;
class Complx {
private:
double real;
double imag;
public:
Complx() {} //构造函数
Complx(double r, double i): real(r), imag(i) {}//带参数的构造函数
Complx operator+(const Complx & c) const {//运算符重载
return Complx(real + c.real, imag + c.imag);
}
Complx & operator=(const Complx &c;) {//第一个&表明返回值是计算结果的引用,第二个&表明使用c的引用,const表明不会改变c
real = c.real;
imag = c.imag;
return *this;//返回对象的引用(如果是前面不是complex &而是complex,那么返回的就是对象的拷贝)
}
friend ostream& operator<<(ostream &os;, const Complx &c;);
double size() const {//const修饰成员函数,表示该函数不能改动类的内容
return sqrt(real*real + imag*imag);
}
};
ostream & operator<<(ostream &os;, const Complx & c) {//conventional的<<操作符重载,用于输出用户自定义的类对象。就按照这个格式写:函数定义为类的友元函数,第一个参数定义为ostream类对象的引用
os << "(" << c.real << "," << c.imag << ")";//第二个实参是用户自己定义的要输出的类对象的引用
return os;//返回值是参数一
}
/*方式1,直接返回类对象
Complx Maximum(const Complx &c1;, const Complx &c2;) {
if (c1.size() > c2.size())
return c1;
else
return c2;
}
*/
//方式二,返回类对象的引用
const Complx & Maximum(const Complx &c1;, const Complx &c2;) {
if (c1.size() > c2.size())
return c1;
else
return c2;
}
int main( )
{
Complx c1(10,30);
Complx c2(13,25);
Complx mx = Maximum (c1,c2);
cout << " c1 = " << c1 << endl;
cout << " c2 = " << c2 << endl;
cout << "Maximum(c1,c2) = " << mx << endl;
Complx c3 (20,40);
Complx c4,c5;
c5 = c4 = c3;
cout << c4 << " got its value from c3" << endl;
Complx c6 = c1 + c2;
cout << " c6 (c1+c2) = " << c6 << endl;
Complx c7;
c1 + c2 = c7;
return 0;
}
得到以下结果:
c1 = (10,30)
c2 = (13,25)
Maximum(c1,c2) = (10,30)
(20,40) got its value from c3
c6 (c1+c2) = (23,55)
上面的方式12都可以,我们用的方式2.因为用引用省去了拷贝(即调用拷贝构造函数)的过程。(返回值类型是引用:那就返回对象的引用;返回值类型直接是类对象:返回的是对象的副本。所以用引用会效率高一些,不用拷贝)另外,因为我们的参数使用的是const型的引用,所以返回值也是const型的,以匹配。(这句话我没懂,为什么返回值非得匹配呢)
2,返回对象的非cons引用
这种用法常见于重载赋值操作符=,和流操作符<<,重载它们,其实返回对象或对象引用都行,引用好一些。关于这部分,建议复习一下操作符重载。
比如链式的赋值:
Complx c3 (20,40);
Complx c4,c5;
c5 = c4 = c3;
c4=c3也就是c4.operator=(c3)也就是operator=(complx &c4,complx &c3)也就是
complx &operator=(complx &c4,complx &c3)
{c4.real=c3.real;
c4.img=c3.img;
return c4;}
被赋给c5。这个例子里返回值类型就不是const的,因为c4是要被改变的。
链式的输出:
cout << c4 << " got its value from c3" << endl;
cout<<c4等价于operator<<(cout,c4),它的返回值是cout的引用,也是非const型的,以便以后它的值再被改变。这里,返回值类型不能直接是对象,因为这样要调用拷贝构造函数,但是ostream类没有public的拷贝构造函数。
3,返回类对象
如果返回的对象是所调用函数的局部对象,那它就不应该被以引用的方式返回,因为在这个函数调用结束的时候局部对象会自动消除,所以不用我们管。也因此,我们绝对不能返回一个局部对象的引用,因为函数调用完的时候它已经不存在了。
举例:
const Complx &complxReturn;(const Complx & c) {
Complx complxObj = c;
return complxObj;
}
这里complxObj就是一个局部变量,我们想得到它,只能返回它的拷贝,不能返回引用。
4,返回const类对象
通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例) ,则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
总结:
1,如果函数返回的是局部变量,那么返回值类型不能是引用或指针。
2,如果函数返回的是类对象,但是该类没有public的拷贝构造函数,比如ostream类,那就返回引用。
3,有的函数,比如重载的=,可以返回对象也可以返回引用,引用比较好,因为效率高。
再总结:除了返回局部对象,一般都是返回引用。
(写的比较乱,还会再改)