我有一个简单的CTest类,具有两个函数-func()
和virtualFunc()
。我仅出于测试目的而在堆栈上创建一个对象,并希望观察其行为。我确实意识到我们应该在堆上使用new
关键字创建一个对象,但是我有兴趣知道对象在堆栈上时虚函数的行为。
使用我当前拥有的代码,当我尝试调用虚拟函数时,这会导致Seg Fault。谁能告诉我为什么虚拟功能导致段错误而非虚拟功能却没有?
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.
}
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
是空指针。
您需要通过调用obj = new CTest来创建对象,而不是obj = NULL