《深度探索C++对象模型》学习笔记(5-7章)
第5章 构造析构和拷贝
虚函数
对于抽象类而言,是否应该自己负责初始化类内的数据成员?(别忘了抽象类也可以有非纯虚函数和数据成员)
- 一般情况下被认为子类要负责从基类继承来的数据成员的初始化
- 或者基类必须提供一个显式的构造函数用于自己数据成员的初始化
- 最好的方法则是将行为和数据分离,提供接口专门用于定义方法
class A_B
{
public:
virtual ~A_B() = 0;
virtual void Say() const = 0;
inline char const* GetData() const { return iData; }
protected:
A_B( char* aData ) : iData( aData ) { }
protected:
char* iData;
};
inline A_B::~A_B() {}
class C_D : public A_B // concrete derived class
{
public:
C_D( char* aData, char* aData2 ) :
A_B( aData ), iData2( aData2 ) { cout<<"c_d ctor"<
纯虚函数
- 拥有定义的纯虚函数(这还叫纯虚函数么)可以在子类中进行调用。不过就是什么用都没有罢了。
//定义
inline void A_B::Say() const { cout<<"hey!"; }
//调用,发现hey!并没有打印出来
virtual void Say() const { A_B::Say(); cout<<"c_d says: "<
- 实际上是否让纯虚函数拥有(没用的)定义由程序员说了算。
- 但唯一的例外是纯虚析构函数,必须像上面那样进行显式定义 A_B::~A_B() {}
- 否则就会出现错误,严格来说并非编译错误,而是链接错误。
- 原因很简单,析构函数和构造函数一样,子类的都会由编译器进行扩充,调用基类的版本。
- 不希望这么定义的话,解决方法只有生命非纯虚的析构函数
Virtual Specification
- 不加选择地将函数设定为virtual在效率上会不升反降,不能依赖编译器的优化
- 应付const也会令人头疼,例如在基类中不需要修改的const ref或者const pointer,到了子类就需要修改了。目前最好的方法是不用const(……无语)
- 需要考虑到的(不全)
- 抽象类的构造函数需要负责初始化自己的数据成员,可以声明为protected避免外部访问
- 缺少多态需求的函数不要设定为virtual,尤其是inline函数
- 慎用const,除非确定派生类也不会修改const修饰的对象
Read more >>>
14 12月 2011 in 未分类, 程序
Comments [3]