继承的困惑

Inheritance Confusion

本文关键字:继承      更新时间:2023-10-16

我一直在开发一个游戏引擎,我遇到了一个问题……目前,我有一个层次结构的类(图像->动画->对象),所有这些都有一个方法get_type(),我有这个问题:

如果我使用new关键字声明派生类,或者静态地声明派生类,我将得到期望的结果:

object instance;
cout << instance.get_type(); //returns an int value  
object* pointer = new(object);
cout << pointer->get_type();

从上面的代码中,控制台输出3。该方法在object:

中声明为

图片类:

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关键字,它会像我期望的那样工作(代码的最后一位返回3)

问题:如何在不使用new关键字的情况下利用对象*指针中的虚拟方法?原因是,我正在用指向这些对象的指针填充一个向量,并在添加它们时创建它们,所以我希望能够做以下事情:

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

和对象[x]->get_type();返回正确的类类型。这是因为我在游戏中使用的事件系统需要origin类类型。

TLDR;我真的不擅长继承,你能帮我吗?

这是因为构造函数和析构函数都在你的代码中运行:

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

&object()创建一个(匿名的,临时的)对象,立即销毁它(因为它是临时的),然后将现在被销毁的对象的地址分配给t。(如果你把警告级别调得足够高,编译器可能会警告你这个表达式。)

试着创建一个在你使用它的时候一直存在的对象:

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

当您使用非虚函数时,在编译时使用指针t的类型来确定要调用哪个方法。在使用虚函数时,对象内部的信息将在运行时的虚分派期间使用,以决定调用哪个函数。由于对象在调用时没有正确构造(因为它已经被析构),因此结果是严格未定义的,但最终调用了错误的函数。