Наследование C ++, базовые функции все еще вызываются при переопределении - PullRequest
3 голосов
/ 06 марта 2010

У меня есть следующие два класса, один наследует от другого

Class A{
  void print(){cout << "A" << endl;}
}

Class B : A{
  void print(){cout << "B" << endl;}
}
Class C : A{
  void print(){cout << "C" << endl;}
}

Тогда в другом классе у меня есть следующее:

vector<A> things;
if (..)
  things.push_back(C());
else if (..)
 things.push_back(B());

things[0].print();

это всегда печатает A
Я бы хотел, чтобы он печатал B или C в зависимости от того, что я добавил в вектор
как мне это сделать?
Я пробовал абстракцию, но я не совсем уверен, как использовать ее в C ++, и она не работает для меня

Ответы [ 3 ]

8 голосов
/ 06 марта 2010

1) Вам нужно объявить print () как virtual в классе A.

2) Ваш вектор неверен - вы не можете хранить там реальные объекты класса А; вам нужно будет хранить указатели на них для правильного поведения (и вам придется убирать за ними позже) и / или использовать что-то вроде boost :: shared_ptr.

8 голосов
/ 06 марта 2010

Как уже упоминалось, вам нужны функции virtual, чтобы включить полиморфное поведение, и вы не можете хранить классы напрямую по значению в vector.

Когда вы используете std::vector<A>, вы сохраняете по значению и, таким образом, объекты, которые вы добавляете, например, через push_back() копируются в экземпляр A, что означает, что вы теряете производную часть объектов. Эта проблема известна как нарезка объектов .

Как уже предлагалось, этого можно избежать, сохранив указатели (или умные указатели ) на базовый класс, поэтому в vector копируются только указатели:

std::vector<A*> things;
things.push_back(new B());
// ... use things:
things[0]->print();

// clean up later if you don't use smart pointers:
for(std::vector<A*>::iterator it = things.begin(); it != things.end(); ++it)
    delete *it;
3 голосов
/ 06 марта 2010

Вам необходимо объявить виртуальную функцию в вашем базовом классе, в данном случае это класс a:

class A{
  virtual void print(){cout << "A" << endl;}
}

Другие классы поймут это, даже если вы не пишете в них виртуальные (но вы можете).

Virtual сообщает компилятору, что функция может быть переопределена. Когда вы не используете виртуальный, это называется скрытием и работает по-другому, как вы обнаружили.

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