1. 函数返回引用类型
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
int a = 0; //数据成员
// 返回引用
A &f1() { return *this; }
// 返回非引用
A f2() { return *this; }
// a+=1
void combine() { a += 1; }
};
int main()
{
A x, y;
x.f1().combine();
//等价于
// A &temp1 = x.f1();
// temp1.combine();
y.f2().combine();
//等价于
// A temp2 = y.f2();
// temp2.combine();
cout << "x.a = " << x.a << endl;
cout << "y.a = " << y.a << endl;
return 0;
}
函数名 | this类型 | *this类型 | 返回类型 |
---|---|---|---|
f1 | A *const | A | A& |
f2 | A *const | A | A |
分析:
- f1的返回类型是A&,x.f1()返回的是对x的引用,对x.f1的操作会相应的修改x。
- f2的返回类型是A,y.f2()返回的是y的副本,对y.f2()的操作不会影响到y。
总结:
- 返回*this的成员函数可以合并在一条语句中。
- 对于返回*this的成员函数,若它的返回类型是引用,则返回值是对类对象的引用;若它的返回类型不是引用,则返回值是类对象的副本。
2. 常量成员函数
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
int a = 0; //数据成员
// 非常量成员函数
A &f1() { return *this; }
// 常量成员函数
const A &f2() const { return *this; }
};
int main()
{
A x1; //非常量
x1.f1();
x1.f2();
const A x2; // 常量
x2.f1(); //错误
x2.f2();
return 0;
}
函数名 | this类型 | *this类型 | 返回类型 |
---|---|---|---|
f1 | A *const | A | A& |
f2 | const A *const | const A | const A& |
分析:
- x1是变量,f2是常量成员函数。x1调用f2时,this=&x1,this指向const A,x1是A,指向常量的对象可以指向相应的非常量对象,x1.f2()正确。
- x2是常量,f1不是常量成员函数。x2调用f1时,this=&x2,this指向A,x2是const A,类型不匹配,x2.f1()错误。
总结:
- 常量对象,以及对常量对象的引用和指针只能调用常量成员函数。
- 非常量对象可以调用常量成员函数和非常量成员函数。重载时编译器优先调用非常量成员函数。
3. 常量成员函数调用顺序
#include <iostream>
using namespace std;
class A
{
public:
int a = 0; //数据成员
A &add()
{
a += 1;
return *this;
}
const A &show() const
{
cout << a << endl;
return *this;
}
};
int main()
{
// 先a+1, 再打印a
A a1;
a1.add(); //this=&a1, this指向A, a1是A
a1.show(); //this=&a1, this指向const A, a1是A
A a2;
a2.add().show();// a2.add()的结果不是常量,可以调用常量成员函数
// 先打印a, 再a+1
A a3;
a3.show(); //this=&a3, this指向const A, a3是A
a3.add(); //this=&a3, this指向A, a3是A
A a4;
a4.show().add(); // 错误,a4.show()的结果是常量。常量对象只能调用常量成员函数,add不是常量成员函数
return 0;
}
函数名 | this类型 | *this类型 | 返回类型 |
---|---|---|---|
add | A *const | A | A & |
show | const A *const | const A | const A & |
分析:
- a1本身不是常量,它可以调用普通成员函数add和常量成员函数show。a1.add()返回一个绑定a1的引用,这个引用对a1.show()无影响。
A a1;
a1.add(); //this=&a1, this指向A, a1是A
a1.show(); //this=&a1, this指向const A, a1是A
//等价于
A &tem1 = a1.add();
a1.show();
- a2本身不是常量,它可以调用普通成员函数add。a2.add()返回一个绑定a2的引用,该引用不是对常量的引用,它可以调用常量成员函数show。
A a2;
a2.add().show();
//等价于
A &temp2 = a2.add();
temp2.show();
- a3本身不是常量,它可以调用常量成员函数show和普通成员函数add。a3.show()返回一个绑定a3的引用,这个引用对a3.add()无影响。
A a3;
a3.show(); //this=&a3, this指向const A, a3是A
a3.add(); //this=&a3, this指向A, a3是A
//等价于
const A &temp3 = a3.show();
a3.add();
- a4本身不是常量,它可以调用常量成员函数show。a4.show()返回一个绑定a4的引用,该引用是对常量的引用,它只能调用常量成员函数,不能调用普通成员函数add。
A a4;
a4.show().add(); // 错误
//等价于
const A &temp4 = a4.show();
temp4.add();
总结:
- 普通成员函数与常量成员函数合并在一条语句时注意其先后顺序,其合并和拆开后含义可能不同,如a1和a2是含义相同,a3和a4含义不同。