条款21:必须返回对象时,别妄想返回其reference
考虑一个用以表现有理数的class,内涵一个函数用来计算两个有理数的乘积:
class Rational {
public:
Rational(int numerator = 0, int denominator = 1);
...
private:
int n, d;
friend
const Rational operator* (const Rational & lhs, const Rational& rhs);
};
上述版本的operator*是以by-value方式返回计算结果的,如果改成reference呢?由于reference指向已有的对象,所以我们需要先创建对象。
const Rational& operator* (const Rational& lhs, const Rational& rhs) {
Rational result(lhs.n * lhs.n, lhs.d * rhs.d); //糟糕的代码
return result;
}
result是一个local对象,在对象退出函数之前会被销毁。因此它返回的reference指向一个已经被销毁的对象。于是,我们考虑在heap内构造一个对象,然后返reference指向它。Heap-based对象有new创建。
const Rational& operator* (const Rational& lhs, const Rational& rhs) {
Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
return *result;
}
new分配的内存,在不需要的时候,我们需要调用delete对他进行释放。
Rational w, x, y, z;
w = x * y * z; //与operator* (operator*(x, y), z)相同
这里,同一个语句内调用了两次operator*,因而两次使用new,也就需要两次delete。但却没有办法取得operator*返回的reference背后隐藏的指针。
一个必须返回新对象的函数的正确写法是:就让那个函数返回一个新的对象。
inline const Rational operator* (const Rational& lhs, const Rational& rhs) {
return Rational(lhs.n * rhs.n, lhs.d * rhs.d);
}
条款22:将成员变量声明为private
请记住
- 切记将成员变量声明为private。这可赋予客户访问数据的一致性、可细微划分访问控制、允诺约束条件获得保证,并提供class作者以充分的实现弹性。
- protected并不比public更具封装性。