Предположим, что у меня есть следующая структура классов. Я хочу иметь возможность определить, к какому типу класса относится элемент в моем векторе Animal, чтобы я мог выполнять над ним методы, специфичные для подкласса. Пример ниже должен продемонстрировать:
#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 я бы сделал так:
if (v.get(i).getClass() == Lion.class) {
((Lion)v.get(i)).chowMeat();
}
if (v.get(i).getClass() == Butterfly.class) {
((Butterfly)v.get(i)).drinkNectar();
}
dynamic_cast
как это сделать правильно. Это некрасиво, потому что, используя его здесь, вы неявно следуете принципу дизайна, который вы должны. Эквивалент Java непривлекателен по той же причине, и это гораздо более очевидно, учитывая то, как он написан. Кстати, используйте конструкции типаforeach
для перебора контейнеров или, по крайней мере, используйте настоящие итераторы вместо индексов. См. также stackoverflow.com/questions/4383250/ . - person Karl Knechtel   schedule 08.12.2010virtual void eat()
, и мы реализуем его таким образом, чтобы Лев ел(а), пережевывая мясо, а Бабочка ела(а), выпивая(ла) нектар. (Думаю, вы могли бы вместо этого назвать егоfeedSelf()
, но это излишне неловко. :) ) - person Karl Knechtel   schedule 08.12.2010