今天碰到的一个笔试题,大家帮忙参考一下
class base
{
public:
base(){fun1();} //1
virtual void fun1(){fun2();} //2
virtual void fun2(){fun3();} //3
virtual void fun3(){} //4
};
class derived: public base
{
public:
derived(){fun1();} //5
virtual void fun1(){fun2();} //6
virtual void fun2(){fun3();} //7
virtual void fun3(){} //8
};
base* ptr = new derived; //按顺序依次写出所有调用的函数的标号
还有就是基类虚函数表指针的值是在何时被修改的
[解决办法]
class base
{
public:
base(){fun1();} //1
virtual void fun1(){fun2();} //2
virtual void fun2(){fun3();} //3
virtual void fun3(){printf("yes\n");} //4
};
class derived: public base
{
public:
derived(){fun1();} //5
virtual void fun1(){fun2();} //6
virtual void fun2(){fun3();} //7
virtual void fun3(){printf("no\n");} //8
};//按顺序依次写出所有调用的函数的标号
int main()
{
base* ptr = new derived;
....
delete ptr;
return 0;
}
函数调用树
main()
[解决办法]
//base* ptr =
+--> new derived;
[解决办法]
[解决办法]
[解决办法]
+ --> operator new (sizeof(derived));// 分配内存, ptr =this =分配的内存;
[解决办法]
[解决办法]
[解决办法]
+---> derived()//ptr = this 分配的内存;
[解决办法]
[解决办法]
[解决办法]
+ --> base() -->base::fun1()-->base::fun2()-->base::fun3(); //this = ptr + 0
[解决办法]
[解决办法]
[解决办法]
+--> derived::fun1()-->derived::fun2()--> derived::fun3(); //this = ptr
....
[解决办法]
+---> delete ptr;
[解决办法]
+-->~derived()//this = ptr;
[解决办法]
[解决办法]
[解决办法]
+--->~base();//this = ptr + 0
------解决方案--------------------
+--> operator delete (ptr);//释放内存
PS:
子类构造函数调用时,
按照如下步骤执行:
1)调用父类构造函数;无论父类构造函数,出不出现在初始化表里。
2)调用成员变量的构造函数;无论成员变量,出不出现在初始化表里。
3)然后执行子类构造函数内部 的代码。
是在子类构造函数调用过程内部,调用的父类构造函数;
析构函数亦然。
基类虚函数表指针的值,是在基类构造的过程中,设置的。
一般是第一个设置的。在基类构造函数的其他代码执行前,设置的。
并且在子类部分构造的时候,有可能会被子类的虚函数表指针覆盖。