使用在堆栈上创建的对象调用虚函数
Calling a virtual function using an object created on stack
我对虚函数的经验和知识不多,所以这个问题可能有一个明显的答案。我只是想了解其中的原因。
我有一个简单的 CTest class,它有两个函数 - func()
和 virtualFunc()
。我纯粹出于测试目的在堆栈上创建一个对象,并想观察它的行为。我确实意识到我们应该在堆上使用 new
关键字创建一个对象,但我有兴趣了解对象在堆栈上时虚函数的行为。
使用我目前的代码,当我尝试调用虚函数时会导致段错误。谁能告诉我为什么虚函数会导致段错误而非虚函数不会?
class CTest {
public:
void func() {
printf("function was called.\n");
}
virtual void virtualFunc() {
printf("virtual function was called.\n");
}
};
int main (int argc, char ** argv) {
CTest * obj = NULL;
obj->func(); // this would print "function called" as what's inside the func()
obj->virtualFunc();
//line above results in segfault because C *obj is on stack;
//You would need to allocated obj on the heap for the virtual function to not Seg Fault.WHY?
//by using "C*obj = new C", I am able to print the contents of virtualFunc() successfully.
}
您需要通过调用 obj = new CTest 来创建对象,而不是调用 obj = NULL
CTest * obj = NULL;
这不是在堆栈上创建对象的方式。这就是您在堆栈上创建对象指针并将其指向任何地方的方式。
你可以简单地做:
CTest obj; // This creates the object, calls constructor
并且由于对象被视为引用,而不是指针,您可以使用
obj.func();
obj.virtualFunc();
等等
要使用指向堆栈变量的指针,您可以这样做:
CTest obj_value; // This actually creates the object
CTest * obj = &obj_value; // This creates pointer to stack object
对象是在栈上还是堆上不影响虚函数的行为。
在你的情况下,obj->func();
有效并且没有段错误的事实实际上是一个不幸的事实。方法不存储在对象内部。它们存储在可执行文件的代码部分,每个整个程序一次,而不是实例,就像常规函数一样。它们也被翻译成类似:
CTest::func(CTest * this) // here this is obj
并且由于 this
无效,但未被使用,所以没有明显的错误发生。
在虚函数的情况下,每个虚函数调用实际上读取 this
以获取所谓的 vtable
。这是您的程序崩溃的地方,因为 this
是空指针。
我对虚函数的经验和知识不多,所以这个问题可能有一个明显的答案。我只是想了解其中的原因。
我有一个简单的 CTest class,它有两个函数 - func()
和 virtualFunc()
。我纯粹出于测试目的在堆栈上创建一个对象,并想观察它的行为。我确实意识到我们应该在堆上使用 new
关键字创建一个对象,但我有兴趣了解对象在堆栈上时虚函数的行为。
使用我目前的代码,当我尝试调用虚函数时会导致段错误。谁能告诉我为什么虚函数会导致段错误而非虚函数不会?
class CTest {
public:
void func() {
printf("function was called.\n");
}
virtual void virtualFunc() {
printf("virtual function was called.\n");
}
};
int main (int argc, char ** argv) {
CTest * obj = NULL;
obj->func(); // this would print "function called" as what's inside the func()
obj->virtualFunc();
//line above results in segfault because C *obj is on stack;
//You would need to allocated obj on the heap for the virtual function to not Seg Fault.WHY?
//by using "C*obj = new C", I am able to print the contents of virtualFunc() successfully.
}
您需要通过调用 obj = new CTest 来创建对象,而不是调用 obj = NULL
CTest * obj = NULL;
这不是在堆栈上创建对象的方式。这就是您在堆栈上创建对象指针并将其指向任何地方的方式。
你可以简单地做:
CTest obj; // This creates the object, calls constructor
并且由于对象被视为引用,而不是指针,您可以使用
obj.func();
obj.virtualFunc();
等等
要使用指向堆栈变量的指针,您可以这样做:
CTest obj_value; // This actually creates the object
CTest * obj = &obj_value; // This creates pointer to stack object
对象是在栈上还是堆上不影响虚函数的行为。
在你的情况下,obj->func();
有效并且没有段错误的事实实际上是一个不幸的事实。方法不存储在对象内部。它们存储在可执行文件的代码部分,每个整个程序一次,而不是实例,就像常规函数一样。它们也被翻译成类似:
CTest::func(CTest * this) // here this is obj
并且由于 this
无效,但未被使用,所以没有明显的错误发生。
在虚函数的情况下,每个虚函数调用实际上读取 this
以获取所谓的 vtable
。这是您的程序崩溃的地方,因为 this
是空指针。