酱坛子

专注C++技术 在这里写下自己的学习心得 感悟 和大家讨论 共同进步(欢迎批评!!!)

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  65 Posts :: 16 Stories :: 236 Comments :: 0 Trackbacks

公告

王一伟 湖南商学院毕业 电子信息工程专业

常用链接

留言簿(19)

我参与的团队

搜索

  •  

积分与排名

  • 积分 - 356706
  • 排名 - 55

最新随笔

最新评论

阅读排行榜

评论排行榜

如果我们现在在设计一个项目

比如需要处理动物,我们会这样设计

                      ----->   lizard class     蜥蜴
class animal
                       -----> chicken class   鸡

class  Animal
{
    pubulic:
         Animal
&   operator   =  ( const  Animal &  rhs);
         
}
;
class  Lizard: public  Animal
{
     
public :
         Lizard
&   operator = ( const  Lizard &  ths);
         .
}
;
class  Chichen: public  Animal
{
      
public :
      Chichen
&   operator = ( const  Chichen &  rhs);
      
}
;

现在我们只演示操作符

现在如果有这样一短代码
Animal* p1 = new Lizard;
Animal* p2 = new Chichen;

如果执行p1 = p2,只有p1的animal部分会被修改,Lizard的其他menber没有被改变,这个是正常的部分赋值现象。

但是实际上我们不希望结果是这样,
如果要执行继承类的operator = 的话,你得在base class 中抽象"="
virtual Animal& operator = (const Animal& rhs);
同样在继承类中

virtual  Chicken& operator=(const Chicken& ths);
virtual  Lizard&    operator=(const Lizard& ths);      //virtual 在继承类中可以省略,但是仍然是抽象的,只是有了实现体而已

这样我们就能实现p1 = p2(我们把一只鸡赋给了蜥蜴,典型的异型赋值);

虽然在 C++中有强烈的型别转换,但是这在C++中是允许的,Animal的virtual "="为异型赋值打开了大门

我们希望当
Animal* pAnimal1= new Lizard;
Animal* pAnimal2= new Lizard;
...
*pAnimal1 =  *pAnimal2;   //呵呵,将蜥蜴给了蜥蜴

但是我们不希望这样的事情发生
Animal* pAnimal1= new Lizard;
Animal* pAnimal2= new Chichen;
...
*pAnimal1 =  *pAnimal2;   //呵呵,将小鸡给了蜥蜴
编译器不能发现问题,但是在运行期会造成错误。

所以我们希望当出现异型赋值的时候,operator = 能对此做一个判断

现在我们能通过 dynamic_cast实现我们的愿望
Lizard& Lizard::operator = (const Animal&  ths)
{
      const Lizard& rhs_liz = dynamic_cast<const Lizard&>(rhs);
      //如果转型失败,dynamic_cast会向外抛出Bad_cast exception
}
这个操作是可行的,但是对于每次赋值操作都是昂贵复杂的似乎有点不划算。
所以我们可以重载下operator = ,只对右边参数为多态形式的指针或引用做dynamic_cast的处理
而对于同型别的指针或者引用 我们则只需要进行copy,copy而已。
so ,我们得有这个:
Lizard& operator = (const Lizard& rhs);

然而对于这样的设计,Effective C++提出了疑问,某些编译器并没有支持dynamic_cast,还有对于exception的捕获大多数程序员并不是太注重这样的设计。所以并不是最好的解决上面部分赋值的办法。

Effective C++提供的模式是
                                                           ------> Lizard
再申请另外一个类AbstractAnimal   ------> Animal
                                                           ------> Chicken
让AbstrctAnimal成为一个抽象类,一个无法被实体化的类,没有任何menber function。Lizard,Animal和Chicken都继承于AbstractAnimal.
这个设计禁止了部分赋值和异型赋值,derive class同样可以调用base class  的operator =;
AbstractAnimal 含有一个抽象类的必须----至少一个纯虚函数。这里设计成他的Destructor.呵呵,这样设计也是为了能很好的支持这些类的多态性,这个就不多说了。


<附:文章非转载,内容虽然简单,请不要砸砖头                           酱菜 2007.02.03凌晨12.30>





posted on 2007-02-04 00:31 @王一伟 阅读(797) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理