ATL中值得注意的C++技术

1. 多重继承中的名字冲突问题。

   class father {
    virtual int faint() { return 0; }
   };

   class mother {
    virtual int faint() { return 1; }
   };

   class baby : public father, public mother {
   ...
    virtual int father::faint() { return 2; }
    virtual int mother::faint() { return 3; }
    //错误,无法区别father::faint和mother::faint。
   };

既然father和baby两个类中的faint都是virtual的,那么应该都可以重载了。

但是这一点总是渴望不可及,因为无法决议。C++的标准解法之一就是声明两个辅助的类。


   class _father : public father {
    virtual int faint() { return fatherfaint(); }
    virtual int fatherfaint() = 0;
   };

   class _mother : public mother {
    virtual int faint() { return motherfaint(); }
    virtual int motherfaint() = 0;
   };

   class baby : public _father, public _mother {
   ...
   //在这里重载fatherfaint和motherfaint两个函数
    virtual int fatherfaint() {..}
    virtual int motherfaint() {..}
   };

但是这样的做法并不是非常好。如果baby这个类重载了faint()函数,那么fatherfaint()和motherfaint()都被遮掩了;如果baby这个类没有重载faint()函数,那么baby就没有办法faint()了,因为他无法决议faint()这个函数来自哪里。仔细想想这还是很合乎逻辑的。孩子生下来谁知道是象爸爸还是象妈妈呢?

[ 深入解析ATL pp 216 ]   很遗憾这个作者没有看过Scott Mayer的Effective C++。 ;((

[ Effective C++ item 43 ]

但是ATL的考虑效率更多一些,而上面的方法多了一层虚函数的调用。所以它提供了不是很pp的解法。
   template<class Deriving>
   struct ATL_NO_VTABLE _father : public father {
    virtual int faint() {
      return static_cast<Deriving*>(this)->fatherfaint(); }
   };

   template<class Deriving>
   struct ATL_NO_VTABLE _mother : public mother {
    virtual int faint() {
      return static_cast<Deriving*>(this)->motherfaint(); }
   };

   class baby : public _father<baby>, public _mother<baby> {
    ...
   };

   ATL_NO_VTABLE是一个宏,定义可以看MSDN:
   #ifdef _ATL_DISABLE_NO_VTABLE
    #define ATL_NO_VTABLE
   #else
    #define ATL_NO_VTABLE __declspec(novtable)
   #endif

这里直接理解做 __declspec(novtable),指明这个类在构造和析构的时候抹掉vtable。注意到类当中根本没有用到vtable,所以抹掉就抹掉吧,无所谓了。这个方法虽然也是万能的,但是在不支持novtable的编译器上作优化却是万万不能。比如gcc。;(

顺便一提的还有所谓的着色技术。以上问题之所以是一个问题是因为编译过程中产生了名字冲突。如果名字不同那就无所谓名字冲突了,而且执行期的程序也不是用名字来查找函数的。因此如果我们上述体系中还有一个中间层,那么你就可以在中间层中耍点小花样来骗过编译器:声明一个新的类而不是从原来的类中继承,保证新的类中函数的摆放和继承回来的类是一样的,同时把名字改一下。这种方法已经过气了,多说无益,不提也罢。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值