本文主要是介绍【More Effective C++】条款35:将非尾端类设计为抽象类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
考虑以下继承场景:
- 通过指针的赋值会出现部分赋值的情况:只修改了Animal的数据成员,Lizard数据没有被修改
class Animal {
public:Animal(int data):data(data) {}Animal& operator=(const Animal& rhs) {if (&rhs == this) return *this;this->data = rhs.data;return *this;}int getData() const { return data; }
public:int data;
};class Lizard : public Animal {
public: Lizard(int data): Animal(data), l_data(data) {}// Lizard& operator=(const Lizard& rhs) {// if (&rhs == this) return *this;// this->data = rhs.data;// return *this;// }
public:int l_data;
};class Chicken : public Animal {
public: Chicken(int data): Animal(data), c_data(data) {}// Chicken& operator=(const Chicken& rhs) {// if (&rhs == this) return *this;// this->data = rhs.data;// return *this;// }
public:int c_data;
};int main() {Animal a1(1);Animal a2(2);std::cout << a1.getData() << std::endl;a1 = a2;std::cout << a1.getData() << std::endl;return 0;
}
可以将拷贝赋值函数改为虚函数:
- 但是又引入了异性赋值的情况,让人难以理解
class Animal {
public:Animal(int data):data(data) {}virtual Animal& operator=(const Animal& rhs) {if (&rhs == this) return *this;this->data = rhs.data;return *this;}int getData() const { return data; }
public:int data;
};class Lizard : public Animal {
public: Lizard(int data): Animal(data), l_data(data) {}virtual Lizard& operator=(const Animal& rhs) {if (&liz_rhs == this) return *this;this->data = rhs.data;return *this;}
public:int l_data;
};class Chicken : public Animal {
public: Chicken(int data): Animal(data), c_data(data) {}virtual Chicken& operator=(const Animal& rhs) {if (&rhs == this) return *this;this->data = rhs.data;return *this;}
public:int c_data;
};int main() {Lizard liz(1);Chicken chick(2);Animal *pAnimal11 = &liz;Animal *pAnimal22 = &chick;*pAnimal11 = *pAnimal22;return 0;
}
解决办法是在拷贝赋值函数中进行类型转换:
- 无法转型的情况抛出异常
class Animal {
public:Animal(int data):data(data) {}virtual Animal& operator=(const Animal& rhs) {if (&rhs == this) return *this;this->data = rhs.data;return *this;}int getData() const { return data; }
public:int data;
};class Lizard : public Animal {
public: Lizard(int data): Animal(data), l_data(data) {}virtual Lizard& operator=(const Animal& rhs) {const Lizard& liz_rhs = dynamic_cast<const Lizard&>(rhs);if (&liz_rhs == this) return *this;this->data = rhs.data;return *this;}
public:int l_data;
};class Chicken : public Animal {
public: Chicken(int data): Animal(data), c_data(data) {}virtual Chicken& operator=(const Animal& rhs) {const Chicken& liz_rhs = dynamic_cast<const Chicken&>(rhs);if (&rhs == this) return *this;this->data = rhs.data;return *this;}
public:int c_data;
};
为了解决简单对象的赋值情况需要赋值转型成本,可以将拷贝函数进行重载
class Animal {
public:Animal(int data):data(data) {}virtual Animal& operator=(const Animal& rhs) {if (&rhs == this) return *this;this->data = rhs.data;return *this;}int getData() const { return data; }
public:int data;
};class Lizard : public Animal {
public: Lizard(int data): Animal(data), l_data(data) {}Lizard& operator=(const Animal& rhs) {if (&liz_rhs == this) return *this;this->data = rhs.data;return *this;}virtual Lizard& operator=(const Animal& rhs) {return operator=(dynamic_cast<const Lizard&>(rhs));}
public:int l_data;
};class Chicken : public Animal {
public: Chicken(int data): Animal(data), c_data(data) {}Chicken& operator=(const Animal& rhs) {if (&rhs == this) return *this;this->data = rhs.data;return *this;}virtual Chicken& operator=(const Animal& rhs) {return operator=(dynamic_cast<const Chicken&>(rhs));}
public:int c_data;
};
未完待续。。。
这篇关于【More Effective C++】条款35:将非尾端类设计为抽象类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!