Путаница с наследованием - PullRequest
9 голосов
/ 24 августа 2011

Хорошо, я работал над игровым движком и столкнулся с проблемой ... В настоящее время у меня есть иерархия классов (image-> animation-> object), каждый из которых имеет метод get_type() и у меня возникает эта проблема:

если я объявляю производный класс, используя ключевое слово new, или статически получаю желаемые результаты:

object instance;
cout << instance.get_type(); //returns an int value  

object* pointer = new(object);
cout << pointer->get_type();

Из приведенного выше кодаконсольные выходы 3. Метод объявлен как таковой в объекте:

Класс изображения:

class image{
public:
  virtual int get_type();
};

int object::get_type(){
  return 1;
}

Класс анимации:

class animation: public image{
public:
  virtual int get_type();
};

int animation::get_type(){
  return 2;
}

Класс объекта:

class object: public animation{
public:
  virtual int get_type();
};

int object::get_type(){
  return 3;
}

Теперь проблема возникает, когда я делаю что-то вроде этого:

object* t = &object();
cout << t->get_type();  

Результат теперь равен 1.

Если я удалю ключевое слово virtual из объявления класса object class, оно будет работать так, как я ожидаю (последний бит кода возвращает 3)

Вопрос: как я могу использовать мои виртуальные методы из указателя объекта * без использования ключевого слова new?Причина в том, что я заполняю вектор указателями на эти объекты и создаю их по мере добавления, поэтому я надеюсь, что смогу сделать что-то вроде следующего:

vector<object*> objects; //not imgs or animations
for (int a = 0; a < 20; a++){
  objects.push_back(&object());
}

И иметь любой объект[х] -> get_type ();вернуть правильный тип класса.Причиной этого является система событий, которую я использую в своей игре, для которой требуется тип класса происхождения ...

TLDR; Я действительно воняю в наследовании, вы можете помочь?

1 Ответ

7 голосов
/ 24 августа 2011

Это потому, что в вашем коде были запущены и конструктор , и деструктор :

object* t = &object();
cout << t->get_type(); 

&object() создает (анонимный, временный) объект, немедленно уничтожает его (потому что он временный), а затем присваивает адрес разрушенного сейчас объекта t. (Ваш компилятор может предупредить вас об этом выражении, если вы увеличите уровень предупреждения достаточно высоко.)

Попробуйте создать объект, который остается в течение всего времени использования:

object my_object();
object *t = &my_object;
cout << t->get_type();

Когда вы используете не виртуальные функции, тип указателя t используется во время компиляции, чтобы определить, какой метод вызывать. Когда вы используете виртуальные функции, информация внутри объекта используется во время выполнения во время виртуальной отправки, чтобы решить, какую функцию вызывать. Поскольку ваш объект не был правильно сконструирован во время вызова (так как он уже был уничтожен), результат строго не определен, но в итоге вызывает неправильную функцию.

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