Effective C++ 随笔(2)
条款5 了解c++默默编写并调用哪些函数
编译器自动生成的copy 构造函数,copy赋值操作符,析构函数,构造函数,这些都是public和inline的,此处inline的意思是他们的定义都是在头文件当中的
假设有一个引用类型的数据成员,那么上面的赋值操作是不对的,因为引用不能改变
条款6 如不想使用编译器自动生成的函数,就该明确拒绝
上面的赋值构造函数,赋值操作符都可以有编译器自动生成,为了拒绝使用上面两种函数,可以创建一个将这种函数定义私用成员的类,从而不会使用这些函数
class Uncopyable { protected: Uncopyable(){} ~Uncopyable(){} private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); } class myclass: private Uncopyable{ };
条款7 为多态基类声明virtual 析构函数
应该经析构函数声明为virtual,从而在多态调用时可以层层将各个类层次的资源析构干净,防止内存的泄露等问题
在某些类里声明纯虚析构函数很方便。纯虚函数将产生抽象类——不能实例化的类(即不能创建此类型的对象)。有些时候,你想使一个类成为抽象类, 但刚好又没有任何纯虚函数。怎么办?因为抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单: 在想要成为抽象类的类里声明一个纯虚析构函数。
这里是一个例子:
class awov { public: virtual ~awov() = 0; // 声明一个纯虚析构函数 };
这个类有一个纯虚函数,所以它是抽象的,而且它有一个虚析构函数,所以不会产生析构函数问题。但这里还有一件事:必须提供纯虚析构函数的定义:
awov::~awov() {} // 纯虚析构函数的定义
这个定义是必需的,因为虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。 这就是说,即使是抽象类,编译器也要产生对~awov的调用,所以要保证为它提供函数体。如果不这么做,链接器就会检测出来,最后还是得回去把它添上。
条款9:决不在构造析构过程中调用virtual函数
在构造函数中虚函数都不是虚函数,因此在使用多态是就会出现问题,假设首先对
条款10 为了实现连锁赋值,赋值操作符必须返回一个引用,指向操作符左侧的实参
widget& operator=(const Widget& rhs){ ...... return *this; }
条款12:赋值对象时勿忘其每一部分 当编写一个copying函数时,应该做到两点:
(1)赋值所有的local变量成员
(2)调用所有base class的copying函数
因为要对一个对象进行赋值,同时也要赋值他的父类中的成员对象,但是这些成员对象有时是private的无法直接访问,这是就需要通过父类的copying函数来进行 例如:
//base class class class1{ public: class1(const class1& c); class1& operator=(const class1&); private: int p; }; class1::class1(const class1& c1){ this->p=c1.p; } class1& class1::operator=(const class1& c1){ p=c1.p; return *this; } //derived class class class2:public class1{ public: class2(const class2&); class2& operator=(const class2&); private: int pp; }; class2::class2(const class2& c2):class1(c2),pp(c2.pp){ } class2& class2::operator=(const class2* c2){ class1::operator=(c2); pp=c2.pp; return *this; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。