条款M33:将非尾端类设计为抽象类:将抽象类赋值运算符函数设为protected

1、常遇到的代码问题:

class Animal { //抽象类
public: 
 Animal& operator=(const Animal& rhs); 
 virtual ~Animal() = 0; //cpp文件必须提供实现
}; 
class Lizard: public Animal { 
public: 
 Lizard& operator=(const Lizard& rhs);  // 派生类赋值运算符函数中需要
 									    // 显示调用基类赋值运算符函数。
}; 
class Chicken: public Animal { 
public: 
 Chicken& operator=(const Chicken& rhs); 
};

Lizard liz1; 
Lizard liz2; 
Animal *pAnimal1 = &liz1; 
Animal *pAnimal2 = &liz2; 
... 
*pAnimal1 = *pAnimal2; // 错误,发生了部分赋值(基类部分)

原因:
1、因为编译器对于非virtual函数(这里的赋值运算符函数)静态绑定,因此调用了pAnimal1所属基类Animal的赋值运算符函数,因此发生部分赋值。
注:函数参数永远是静态绑定。

2、解决方法:
将非尾端类设计为抽象类;将抽象类赋值运算符函数设为protected

class Animal { //抽象类
protected:
 Animal& operator=(const Animal& rhs); 
public: 
 virtual ~Animal() = 0; //cpp文件必须提供实现
}; 
class Lizard: public Animal { 
public: 
 Lizard& operator=(const Lizard& rhs); // 派生类赋值运算符函数中需要
 									   // 显示调用基类赋值运算符函数。
}; 
class Chicken: public Animal { 
public: 
 Chicken& operator=(const Chicken& rhs); 
};

Lizard liz1; 
Lizard liz2; 
liz2 = liz1; //正确,在派生类中,基类protected函数可见为public。
Animal *pAnimal1 = &liz1; 
Animal *pAnimal2 = &liz2; 
... 
*pAnimal1 = *pAnimal2; // 编译错误,调用protected函数错误

解释:
1、同类型间的赋值被允许;
2、部分赋值被禁止(给出编译错误,调用基类protected函数失败);
3、派生类的赋值操作函数可以调用基类的赋值操作函数。

3、其他解决方法:不好
将赋值运算符函数设置为virtual,然后在函数内通过RTTI判断参数真实类型。

class Animal { 
public: 
 virtual Animal& operator=(const Animal& rhs); 
 ... 
}; 
class Lizard: public Animal {
public: 
 virtual Lizard& operator=(const Animal& rhs); 
 ... 
}; 
class Chicken: public Animal { 
public: 
 virtual Chicken& operator=(const Animal& rhs); 
 ... 
};

Lizard liz; 
Chicken chick; 
Animal *pAnimal1 = &liz; 
Animal *pAnimal2 = &chick; 
... 
*pAnimal1 = *pAnimal2; // 调用Lizard类函数,函数内判断出参数类型不匹配,
					   // 给出不能赋值的提示。

解释:
1、因为使用虚函数(多态),所以可以正确调用所需类的成员函数;
2、因为使用虚函数,所以派生类中需要重写基类函数,所以赋值运算符函数参数都变为const Animal& rhs,所以要在函数中判断参数真实类型。
3、函数中动态判断类型开销大,因此不适用。

总结:

1、在抽象类中,常把赋值运算符声明为:protected:以便确保当目标静态类型是抽象类(基类)时,赋值操作被禁止(防止部分赋值)。
2、尽量将非尾端类设计为抽象类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值