我有以下代码,其中我有一个基类类型unique_ptr<Animal>
的智能指针。但是我想用new Bird()
存储派生对象。因为它是一个指针,所以效果很好。这是一种好的做法还是在扩展我的代码时会遇到问题?
接下来,我想调用派生对象的方法:eat()
。因此,我需要将指针转换为派生类型。这种dynamic_cast的使用是否正确?是否有任何解决方案可能更适合此问题(问题:我不知道我有哪种对象)?
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class Animal {
public:
Animal() {}
virtual void move() {cout<<"ooopsooops\n";}
};
class Fish : public Animal{
public:
Fish() {}
void move() {cout<<"swimswim\n";}
};
class Bird : public Animal{
public:
Bird() {}
void move() {cout<<"flyfly\n";}
void eat() {cout<<"pickpick\n";}
};
int main()
{
Animal().move(); //ooopsooops | good!
Animal* ptr(new Bird());
ptr->move(); //flyfly | perfect!
unique_ptr<Animal> s_ptr(new Bird());
s_ptr->move(); //flyfly | perfect!
vector<unique_ptr<Animal>> v;
v.emplace_back(new Animal());
v.emplace_back(new Fish());
v.emplace_back(new Bird());
for(auto& i : v)
i->move(); //ooopsooops | swimswim | flyfly | exellent!
//v.at(2)->eat(); Does not work -> use dynamic_cast
auto d_ptr(dynamic_cast<Bird*>(v.at(2).get()));
if(d_ptr)
d_ptr->eat(); //pickpick | very good!
return 0;
}
答案 0 :(得分:0)
实际上不推荐你这样做,你的代码(使用dynamic_cast
)精确地解除了继承旨在为你提供的好处,即不需要知道什么对象的类。这看起来像一个练习的例子,但是从表面上看,所有的动物都吃,所以这应该是你基类的一种方法。如果调用Animal::move
实际上是'oops',那么这个基类应该是抽象的。另外,在派生类中省略virtual
,这至少是一个设计错误。所以我会沿着这些方向重做:
class Animal {
public:
Animal() {}
virtual void eat() = 0;
virtual void move() = 0;
};
class Fish : public Animal{
public:
Fish() {}
virtual void eat() override {cout<<"eateat\n";}
virtual void move() override {cout<<"swimswim\n";}
};
class Bird : public Animal{
public:
Bird() {}
virtual void eat() override {cout<<"pickpick\n";}
virtual void move() override {cout<<"flyfly\n";}
};
注意使用override
说明符,它对于在编译时捕获继承错误非常有用。您将无法再写Animal().move();
但这没关系;如果你真的想要一个具体的基类,那么把我在Animal
上面的内容放到AnimalBase
类中,并根据需要重新设计Animal
。