首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在基向量的元素上调用派生方法(给出的示例)

在基向量的元素上调用派生方法(给出的示例)
EN

Stack Overflow用户
提问于 2010-12-08 08:39:35
回答 4查看 213关注 0票数 2

假设我有如下的类结构。我希望能够确定我的Animal向量中的元素是什么类类型,这样我就可以对它执行子类特定的方法。下面的示例将演示:

代码语言:javascript
复制
#include <iostream>
#include <vector>

using namespace std;

class Animal {
    public:
    int foodcount;

    Animal() {
        foodcount = 0;
        cout << "An animal was created.\n";
    }
    virtual ~Animal() {
        cout << "An animal was destroyed.\n";
    }
};

class Lion : public Animal {
    public:
    Lion() {
        cout << "A lion was created.\n";
    }
    virtual ~Lion() {
        cout << "A lion was destroyed.\n";
    }
    void chowMeat(int howmuch) {
        foodcount += howmuch;
    }
};

class Butterfly : public Animal {
    public:
    Butterfly() {
        cout << "A butterfly was created.\n";
    }
    virtual ~Butterfly() {
       cout << "A butterfly was destroyed.\n";
    }
    void drinkNectar(int howmuch) {
       foodcount += howmuch;
    }
};

int main() {
    Animal* A = new Lion();
    Animal* B = new Butterfly();
    vector<Animal*> v;

    v.push_back(A);
    v.push_back(B);

    // a little later

    for (int i=0; i<v.size(); i++) {
        if (v[i] is a Lion) v[i]->chowMeat();  // will not work of course
        if (v[i] is a Butterfly) v[i]->drinkNectar();   // will not work of course
    }

    std::cin.get();
    return 0;
}

显然,标记的代码不会工作,但我该如何做我想做的事情呢?有没有我应该遵循但没有遵循的变通办法或设计原则?我研究过dynamic_cast,但我知道这并不美观。那么我应该怎么做才是正确的呢?

在Java中,我会这样做:

代码语言:javascript
复制
if (v.get(i).getClass() == Lion.class) {
    ((Lion)v.get(i)).chowMeat();
}
if (v.get(i).getClass() == Butterfly.class) {
    ((Butterfly)v.get(i)).drinkNectar();
}
EN

回答 4

Stack Overflow用户

发布于 2010-12-08 08:42:11

理想情况下,您应该向基类void eat(int quantity)添加一个虚函数,并在派生类中覆盖该函数。

在这种情况下,将函数设为非虚函数并在基类中实现它可能是有意义的,因为两个派生类做的是完全相同的事情。

除此之外,您可以使用dynamic_cast测试对象的动态类型:

代码语言:javascript
复制
if (Lion* lion = dynamic_cast<Lion*>(v[i])) {
    lion->chowMeat(42); 
}
else if (Butterfly* butterfly = dynamic_cast<Butterfly*>(v[i])) {
    butterfly->drinkNectar(42);
}
// etc.

(另一方面,您需要非常小心地在C++中使用裸指针;在手动管理资源的地方很难编写正确的代码。在您的示例中,您没有释放AB所指向的对象,因此泄漏了它们。考虑使用智能指针,如shared_ptr,自动管理您的资源。)

票数 1
EN

Stack Overflow用户

发布于 2010-12-08 08:41:27

循环的目的是什么?是用来吃东西的吗?在这种情况下,将virtual void consumeFood(int howMuch)添加到基类,并在派生类中重写它。

票数 0
EN

Stack Overflow用户

发布于 2010-12-08 09:02:20

为什么不吃()呢?

代码语言:javascript
复制
class Animal {
    public:
    int foodcount;

    Animal() {
        foodcount = 0;
        cout << "An animal was created.\n";
    }
    virtual ~Animal() {
        cout << "An animal was destroyed.\n";
    }
    virtual void eat(int howMuch) {
        foodcount += howmuch;
    }
};

class Lion : public Animal {
    public:
    virtual void eat(int howmuch) {
        Animal::eat(howmuch + 19);
    }
};

class Butterfly : public Animal {
    void eat(int howmuch) {
       Animal::eat(howmuch / 1000);
    }
};

class Tribble: public Animal
{
    void eat(int howmuch) {
       throw DontFeedTribles();
    }
};

int main() {
    std::auto_ptr<Animal> A = new Lion();
    std::auto_ptr<Animal> B = new Butterfly();
    vector<Animal*>  menagerie;

    menagerie.push_back(A.get());
    menagerie.push_back(B.get());

    BOOST_FOREACH(Animal* animal, menagerie)
    {
        animal->eat(10000);
    }

    std::cin.get();
    return 0;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4383174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档