Welcome to ErranLi's Blog!

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  106 Posts :: 1 Stories :: 97 Comments :: 0 Trackbacks

常用链接

留言簿(12)

搜索

  •  

积分与排名

  • 积分 - 169363
  • 排名 - 151

最新评论

阅读排行榜

    
如果在派生类中要重载派生类的operator = ,那么在基类中一般不要重载operator = ,因为这样会带来很多麻烦.

定义了两个类:
 class CBase
{  
public:
   CBase()
   {
        cout<<"CBase constructing ..."<<endl;
    }
   virtual ~CBase()
   {
        cout<<"CBase destructing ..."<<endl;
    }
public:
   CBase & operator=(const CBase & ent)
   {
         cout<<"CBase operator = ... "<<endl;
         return *this;
    }
};

class CDerive: public CBase
{
public:
     CDerive()
     {
           cout<<"CDerive constructing 
     }
     ~CDerive()
     {
            cout<<"CDerive destructing ..."<<endl;
      } 
public:
     CDerive & operator=(const CDerive & ent)
    {
           cout<<"CDerive operator = ... "<<endl;
           return *this;
     }
}

定义如下操作:

CBase * b1 = new CDerive();
CBase * b2 = new CDerive();

(*b1) = (*b2);

可以看到其输出为:
CBase constructing ...
CDerive constructing ...
CBase constructing ...
CDerive constructing ...
CBase operator = ...
CDerive destructing ...
CBase destructing ...
CDerive destructing ...
CBase destructing

而实际上,操作(*b1) = (*b2)是想把b1,b2实际所指类型的两个对象之间进行赋值,但是它只是调用了基类的赋值操作,没有执行其本身派生类的赋值操作。

发现有两种方法可以解决这个问题,如果能够知道基类指针实际所指的是哪个派生类的的对象,直接类型转换就可以了:

(*((CDerive*)b1)) = (*((CDerive*)b2));

这样可以发现输出了:CDerive operator = ... 。但是当要定义基类的指针的时候,往往隐藏了具体的派生类,即往往不知道指针到底实现的是哪个派生类,所以这种方法有很多局限性。

这时候可以采用第二种方法,即在派生类中重载基类的赋值操作符,即首先把基类的operator=定义为virtual operator=,再在派生类中重载这个,如:

CBase & operator=(const CBase & ent)
 {
       const CDerive * p = reinterpret_cast<const CDerive *>(&ent);
       return operator=((*p));
 }

好的,当再执行 (*b1) = (*b2) 的时候就可以看到输出:CDerive operator = ... 。


 在此发现在派生类中重载派生类的operator =的时候,如果在基类中也重载operator = ,这样会带来很多麻烦,可能会丢失很多也许不想丢失的数据。
 
同样,依次还存在问题:
CBase * b1 = new CDerive();
CDervie * d1 = new CDerive();

(*b1) = (*d1);

CBase * b2 = new CBase ();
CDervie * d2 = new CDerive();
(*b2) = (*d2);

所以我个人觉得,如果一个基类有很多个派生类的,而派生类中又重载了派生类本身的赋值操作符的时候,则基类中最好不要去重载赋值操作符,不如直接用函数去赋值。正如所说那样,运算符重载只是为了一种语法上的方便,是另外一种函数调用方式,如果不能带来方便,就没必要了,还不如直接用函数去代替。


.............敬请指点..................
posted on 2006-05-22 01:09 erran 阅读(1608) 评论(2)  编辑 收藏 引用 所属分类: C & C++

Feedback

# re: C++随笔 关于virtual operator = 2006-06-02 08:26 LOGOS
嗯,在有继承的体系中,重载赋值操作符的确会发生很多灾难性的事情。
增加知识了。  回复  更多评论
  

# re: C++随笔 关于virtual operator = 2009-11-23 13:58 Noock Tian
CBase & operator=(const CBase & ent)
{
const CDerive * p = reinterpret_cast<const CDerive *>(&ent);
return operator=((*p));
}
这个实现是有问题的,返回值应该是
CDerived& operator=(const CDerived& other)
{
CBase::operator=(other);
// Copy new members in CDerived
return *this;
}
  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理