(智能)指向存储派生对象的基类的指针;这是正确的吗?好的做法?

时间:2015-03-02 21:42:49

标签: pointers c++11 inheritance smart-pointers dynamic-cast

我有以下代码,其中我有一个基类类型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;
}

1 个答案:

答案 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