1. 为驳回编译器自动(暗自)提供的机能,可将相应的成员函数声明为 private 并且不予实现。使用像 Uncopyable 这样的 base class 也是一种做法。
问题: 现有一个类,它不希望对它的对象采用拷贝构造和拷贝赋值的操作。但如果不声明拷贝构造和拷贝赋值函数,而某些人尝试调用它们,编译器会自动声明它们。如何解决该问题呢?
粗糙地解决: 所有编译器产出的函数都是 public。为阻止这些函数被创建出来,你得自行声明它们,但这里并没有什么需求使你必须将它们声明为public。因此你可以将 copy 构造函数或 copy assignment 操作符声明为private。由此,你阻止了编译器暗自创建其专属版本;而令这些函数为 private,使你得以成功阻止人们调用它。
class HomeForSale {
public:
...
private:
...
HomeForSale(const HomeForSale&); //只有声明
HomeForSale& operator=(const HomeForSale&);
}
但若不慎在 member 函数或 friend 函数中调用它们,则会在编译期出错,将问题的发现提前到编译期也是一种好事。
最佳的解决: 继承一个类。
class Uncopyable {
protected:
Uncopyable() {} // 允许derived对象构造和析构
~Uncopyable() {}
private:
Uncopyable(const Uncopyable&); // 但阻止copying
Uncopyable& operator=(const Uncopyable&);
}
为阻止 HomeForSale 对象被拷贝,我们只需要继承 Uncopyable:
// 该类不再声明copy构造函数和copy assign操作符
class HomeForSale: private Uncopyable {
...
};
这行得通,因为只要任何人——甚至是 member 函数或 friend 函数——尝试拷贝 HomeForSale 对象,编译器便试着生成一个 copy 构造函数和一个 copy assignment 操作符,而正如条款12所说,这些函数的“编译器生成版”会尝试调用其 base class 的对应兄弟,那些调用会被编译器拒绝,因为其 base class 的拷贝函数是 private。
评论区