考虑以下继承场景:
- 通过指针的赋值会出现部分赋值的情况:只修改了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;
};
未完待续。。。