effective C++ 读书笔记(剩下的内容 除了template部分)
1:
编译器拒绝将virtual 函数 声明为inline 的
这是显而易见的 因为virtual 函数 只有在运行期间 才确定最终要调用哪个函数 而inline函数 在编译期间 就确定要调用哪个函数了
同时在debug中 可以在inline 函数中设置断点!
对于inline 函数:
inline 函数 无法 随着 程序库的升级而升级
如果f 是函数库中的一个inline函数 客户将f() 编入其程序中一旦程序库设计者决定改变 f() 所有用到f() 的客户端 程序都必须重新编译
如果f() 是非inline函数 客户端就只需要重新链接就好
如果程序库采用动态链接 升级版函数甚至可以 不知不觉的 被应用程序 吸纳
2:
class base
{
public:
base(){};
virtual ~base(){};
virtual void mf1() = 0;
virtual void mf1(int);
virtual void mf2();
virtual void mf3();
virtual void mf3(double);
};
class drived: public base
{
public:
drived(){};
virtual ~drived(){};
virtual void mf1();
virtual void mf3();
void mf4();
};
main()
{
drived *d = new drived();
d->mf3(); // 调用成功
d->mf3(123); //调用失败
}
注意! 编译器在寻找mf3的定义时 会先在main的作用于中寻找 之后在drived的作用于中寻找 应为drived 中定义了一个mf3 则它就会将base类中mf3的声明遮掩掉!
3:
接口继承 和 实现继承 的不同
pure virtual 函数 之具体指定 接口继承 其实它也可以有实现 但是意义不大
impure virtual 函数 具体指定 接口继承 给出默认的 实现继承
non-virtual 函数具体指定 接口继承 以及强制性实现继承
4:
non-virtual interface 手法 Template Method 设计模式的一个特例
class NVI
{
public:
void funcInterface(NVI *nvi) // wrapper!
{
//if(nvi)
{
// Mutex lock(m_threadMutex);
// LOG
func(nvi);
}
}
virtual ~NVI(){};
private:
virtual void func(NVI *)
{
cout<<"real func body!"<<endl;
}
};