gpt4 book ai didi

c++ - 在不知道类结构的情况下重载赋值运算符

转载 作者:搜寻专家 更新时间:2023-10-31 01:05:21 25 4
gpt4 key购买 nike

假设有一个类Human,它有一个宠物列表。宠物可以是 CatDog。为了避免对象切片,我将列表中的对象声明为指向基类 Pet 的指针。

现在,当我想通过调用 operator= 复制一个人时,我需要检查每只宠物是狗还是猫。使用这种方法,例如,如果我添加一种新类型的宠物,我们称它为Fish,我必须记住添加(在Human::operator= 中)一个检查宠物是否为鱼的 if 语句。

我的问题是:是否可以在不向下转换(不检查宠物可以是的所有类型)的情况下为类 Human 实现 operator=(或复制构造函数)?

class Pet {
public:
virtual std::string getType()=0;
};

class Cat : public Pet {
public:
std::string getType() {
return "Cat";
}
};

class Dog : public Pet {
public:
std::string getType() {
return "Dog";
}
};

class Human {
public:
void addPet(Pet* pet) {
this->pets.push_back(pet);
}

virtual std::list<Pet*> getPets() const {
return this->pets;
}

Human& operator=(const Human& other) {
std::list<Pet*> pets=other.getPets();
std::list<Pet*>::iterator i=pets.begin(), end=pets.end();
for(;i!=end;i++) {
if(dynamic_cast<Cat*>(*i)) {
this->pets.push_back(new Cat);
} else if(dynamic_cast<Dog*>(*i)) {
this->pets.push_back(new Dog);
}
}
return *this;
}
private:
std::list<Pet*> pets;
};

int main()
{
Human* joe=new Human;
joe->addPet(new Cat);
joe->addPet(new Dog);
Human bob=*joe;
delete joe;
std::list<Pet*> pets=bob.getPets();
std::list<Pet*>::iterator i=pets.begin(), end=pets.end();
for(;i!=end;i++) {
std::cout<<(*i)->getType()<<std::endl;
}
}

最佳答案

通常你所做的是正确实现每个派生类的拷贝构造函数(在很多情况下这意味着只保留默认的)。

然后,你在你的基类中声明类似

virtual Base* clone()=0;

并且在每个派生类中实现为:

virtual Base* clone() 
{
return new Derived(*this);
}

现在,每次您想要类层次结构对象的拷贝时,只需调用其clone() 方法即可。这避免了切片,因为调用的克隆版本是实际类型之一,因此调用了正确的复制构造函数。

关于c++ - 在不知道类结构的情况下重载赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22669732/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com