C++-链式调用const成员函数

164 阅读2分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」 假设定义了一个类A,A包含一个int类型的数据成员n、print成员函数和set成员函数,print成员函数打印n值,set成员函数改变n值。由于print不会改变数据成员,因此应声明为const成员,另外又因为是const成员,所以隐式传入的this指针是const A 类型,返回引用是为了方便链式调用,此时this是const A 类型,所以返回值是const A &类型,代码如下:

class A {
	int i = 0;
public:
	const A &print() const {
		cout << i<<endl;
		cout << "const";
		return *this;
	}

	A & set(int n) {
		i = n;
		return *this;
	}
};

当我们使用如下代码:

int main() {
	A a;
	a.print().set(7);
}

会发生报错,因为print返回的是const A &类型,而const对象无法调用非const成员函数,也无法修改const对象数据成员。解决方法是重载print函数

class A {
	int i = 0;
public:
	const A &print() const {
		cout << i<<endl;
		cout << "const";
		return *this;
	}
	A &print() {
		cout << i << endl;;
		cout << "non-const";
		return *this;
	}

	A & set(int n) {
		i = n;
		return *this;
	}
};

const A &是底层const,因此print可以成功重载(顶层const无法重载)。对const版本的print来说,隐式传入的this指针是const A * 类型,而非const版本的print函数隐式传入的是A *类型,根据最佳匹配原则,如果是A类型的对象调用print,将调用非const版本,因为相比const版本,this指针不需要进行类型转换,此时返回值是非常量因此可以调用set函数;如果是const A类型的对象调用print,将调用const版本print,因为const A *无法转换为A *,唯一匹配的是const版本print。

知识点:

  1. 底层const可以重载,顶层const无法重载
  2. 成员函数调用时隐式传入this指针,指向调用的对象
  3. const对象只能调用const成员函数;const对象的值不能被修改,在const成员函数中修改const对象数据成员的值是语法错误;在const函数中调用非const成员函数是语法错误。