这道金山的面试题怎么理解?请教
发布网友
发布时间:2022-05-29 20:02
我来回答
共2个回答
热心网友
时间:2022-05-24 06:00
这道题考察了好几个方面:
1.全局变量的生命周期
2.类中静态成员的生命周期
3.构造函数和析构函数中对虚函数的调用
4.虚析构函数
把这几方面搞清楚了这道题就很容易了
全局变量是需要在进入main()函数前即初始化的,所以在一个程序中一个全局变量的构造函数应该是第一个被调用的,比main()函数都要早。同时他又必须在main()函数返回后才被销毁,所以他的析构函数是最后才被调用。
而一个类中的静态成员可以看成是一个有效范围受了*的全局变量。他的生命周期与一个全局变量相同,但他只能在这个类的范围内使用。
然后是构造函数和析构函数。在构造函数和析构函数中调用虚函数的话会破坏虚函数的虚拟性(多态性),而只能当作普通函数调用(在这两个函数执行时类的对象有可能是不完整的,无法确定继承的调用链),所以通常应尽量避免在构造函数和析构函数中调用虚函数。
一个类如果是作为基类让其他类来继承的,则他需要把析构函数声明为虚函数,这样在delete一个派生类的对象时才能由多态性调用该派生类所对应的析构函数;否则调用的都是基函数的析构函数。
之后再看题目就很清楚了。Derive类中有一个静态成员,则该成员的构造函数应当最先被调用。之后进入main()函数,new了一个Derive对象,则应顺次调用基类和派生类的构造函数,但基类的构造函数中调用了一个虚函数,这个函数只能被当成普通函数对待,不具备多态性,所以实际调用的仍是基类的Init()函数而不是派生类的。后面继续调用派生类的构造函数。然后是DestroyObj()函数,由多态性pOb->Dump()调用的是派生类的Dump()函数,所以输出了m_nVal的值。再然后是销毁对象,基类析构函数声明为虚函数,所以这里应依次调用派生类和基类的的析构函数。先是输出Derive::~Derive(),然后,基类的析构函数中又调用了一个虚函数,将它作为普通函数调用。。。main()函数终于执行完了,退出后销毁类Derive中的静态成员,调用他的析构函数。
另:如果把Value Derive::m_Val=0;语句屏蔽掉,相当于没有为他初始化,即没有分配空间,编译器会当成他是一个在其他文件中定义的变量,所以编译时应该没问题,但是链接时会报错。
热心网友
时间:2022-05-24 07:18
不是虚构函数,是析构函数
输出的结果
Call Value::Value(int nValue)
Call Base::Init()
Call Derive::Derive()
Value::m_nVal=0
Call Derive::~Derive()
Call Base::Release()
Call Value::~Value()
问题回答:
1.构造函数在你实例化一个对象时调用,析构函数就是在销毁时调用
2.可以定义为虚析构函数。
这样子类对象被释放时,会调用父类的析构函数和自身的析构函数,确保资源得到释放
补充问题的回答:
1.static的变量一般在main函数入口之前被初始化,在Derive类的构造函数之前
2.static变量必须在编译的时候就赋值