如果我们现在在设计一个项目
比如需要处理动物,我们会这样设计
-----> 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>