class Widget { Widget(); //default构造函数 Widget(const Widget& rhs); //copy构造函数 Widget& operator=(const Widget& ths); //copy assignment操作符 } Widget w1; //调用default构造函数 Widget W2; //调用copy构造函数 w1 = w2; //调用copy assigment操作符当你看到赋值符号时请小心,因为"="语法也可用来调用copy构造函数:
class A { public: explicit A(int x){} }; void doSomething(A aObject); //函数,接受一个类型为A的对象 A a(20); doSomething(a); //正确 doSomething(20); //错误,使用explicit声明了构造函数,无法进行隐式转换
class HomeForSale { public: ... private: ... HomeForSal(const HomeForSale&); //只有声明 HomeForSale& operator=(const HomeForSale); };有了上述的class定义,当客户企图拷贝HomeForSale对象,编译器会阻挠他。哪果你不慎在member函数或者friend函数之内那么做,轮到连接器发出抱怨。我们可以定义一个专门的base class,将连接期错误移至编译期:
class Uncopyable{ protected: Uncopyable() {} //允许derived对象构造和析构 ~Uncopyable() {} private: Uncopyable(const Uncopyable&); //但阻止copying Uncopyable& operator=(const Uncopyable&); }为阻止HomeForSale对象被拷贝,我们唯一需要做的是继承Uncopyable。当尝试拷贝HomeForSale对象,编译器便试着生成一个copy构造函数和一个copy assignment操作符,这些函数的“编译器生成版”会尝试调用其base class的对应兄弟,那些调用会被编译器拒绝,因为其base class的拷贝函数是private。boost中也提供了这样的base class,名为noncopyable。
class AWOV { public: virtual ~AWOV() = 0; //声明pure virtual析构函数 }注意一个问题,你必须为这个pure virual析构函数提供一份定义:
Widget& Widget::operator=(const Widget& rhs) { delete pb; pb = new Bitmap(*rhs.pb); //自我赋值时,pb已经删除了 return *this; }我们可以使用“证同测试”达到“自我赋值”的检验目的:
Widget& Widget::operator=(cosnt Widget& rhs) { if (this == &rhs) return *this; //证同测试 delete pb; pb = new Bitmap(*rhs.pb); return *this; }这样做行得通,但是存在异常方面的麻烦,如果"new Bitmap"导致异常,问题就出现了。其实还有一种办法,我们只需要注意在复制pb所指东西之前别删除pb:
Widget& Widget::operator=(cosnt Widget& rhs) { Bitmap* pOrig = pb; pb = new Bitmap(*rhs.pb); delete pb; return *this; }省去了证同测试。
摘自Effective C++
PS :