C ++ Производные классы как владельца, так и дочерних классов - PullRequest
2 голосов
/ 15 марта 2012

Итак, предположим, у меня есть класс животных, управляемый классом zoo.

Animal is an abstract class to be derived by other real animal classes
class Animal{
public:
  Animal();
  virtual ~Animal() = 0;
  //Various animal related functions
}

class Zoo{
public:
  Zoo();
  virtual ~Zoo();
  virtual void updateAll();
  //And various other functions dealing with animals
private:
  vector<animal*> animals
}

Теперь скажите, что я хочу создать bird_zoo, и я хочу повторно использовать большую часть кода, используемого в классе Zoo и классе Animal.

Итак, я делаю птичий класс

class Bird : public Animal{
public:
  Bird();
  virtual ~Bird();
  //all the various functions derived from Animal class
  virtual void fly(); //New function that Animal didn't have
}

class Bird_Zoo : public Zoo{
public:
  Bird_Zoo();
  virtual ~Bird_Zoo();
  //And various other functions dealing with animals, derived from Zoo
  virtual void flyAll(); //New function that Zoo didn't have
private:
  //vector<??????> birds
}

Как мне эта функция Bird_Zoo справиться с имеющимися у нее птицами?Если я останусь с vector<Animal*> из класса Zoo, как я могу позвонить fly()?Мне действительно нужно каждый раз приводить его в Bird*?Есть ли способ концептуально «перегрузить» vector<Animal*> как vector<Bird*>, чтобы все старые функции Zoo по-прежнему работали нормально?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 16 марта 2012

Еще одна возможность - использовать шаблоны.

class Zoo {
  // ...
  virtual void updateAll() = 0;
};

template <typename T,
          typename = typename enable_if<is_base_of<Animal, T>::value>::type>
class ZooWithAVector : public AbstractZoo {
public:
  virtual void updateAll() { /* ... */ }
  // Various functions dealing with T-animals
private:
  vector<T*> animals;
};

typedef ZooWithAVector<Animal> TypicalZoo;

class BirdZoo : public ZooWithAVector<Bird> {
  virtual void flyAll() { /* work with the vector<Bird> */ }
};
1 голос
/ 15 марта 2012

Ваш дизайн неисправен. Теоретически, вы бы подумали, что Bird_Zoo - это Zoo. И это. Но не так, как вы его смоделировали.

Вы видите, что в вашем дизайне Zoo содержит коллекцию любого вида Animal, тогда как Bird_Zoo - нет. Таким образом, если вы решили смоделировать его следующим образом, Bird_Zoo больше не будет Zoo.

Вы можете либо не использовать наследование для этого, либо, что я бы сделал, удалить vector<Animal*> из базового класса.

1 голос
/ 15 марта 2012

Я бы посоветовал вам не иметь vector<animal*> участника в Zoo.Базовый класс (особенно абстрактный) должен реализовывать только то, что является общим для всех потенциальных производных классов.

Вместо этого у вас может быть General_Zoo расширяющийся класс Zoo, который может обрабатывать все типы животных.Так что General_Zoo будет родным классом Bird_Zoo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...