一道C++笔试题说一些知识

         C/C++程序员的求职路上,在笔试中经常会遇到的题目就是继承方面还有构造函数方面的知识,下面我从一个例子给大家讲解一下这其中的知识点。

         先看下面这个代码:

#include <iostream>

using namespace std;

 

class B

{

public:

         B()

         {

                   init();

         }

         B(int i)

         {}

         virtual void init()

         {

                   cout<<"Base::init()"<<endl;

         }

         virtual void Func()

         {

                   cout<<"Base::Func()"<<endl;

                   virtual_Test();

                   non_virtual_Test();

         }

         void Func1()

         {

                   cout<<"Base::Func1()"<<endl;

                   virtual_Test();

                   non_virtual_Test();

         }

         virtual void virtual_Test()

         {

                   cout<<"Base::virtual_Test()"<<endl;

         }

         void non_virtual_Test()

         {

                   cout<<"Base::non_virtual_Test()"<<endl;

         }

         virtual void Delete()

         {

                   cout<<"Base::Delete()"<<endl;

         }

         ~B()

         {

                   Delete();

         }

};

 

class D:public B

{

public:

         D():B()

         {

                   init();

         }

         void init()

         {

                   cout<<"Derived::init()"<<endl;

         }

         void Func()

         {

                   cout<<"Derived::Func()"<<endl;

                   virtual_Test();

                   non_virtual_Test();

         }

         void Func1()

         {

                   cout<<"Derived::Func1()"<<endl;

                   virtual_Test();

                   non_virtual_Test();

         }

         void virtual_Test()

         {

                   cout<<"Derived::virtual_Test()"<<endl;

         }

         void non_virtual_Test()

         {

                   cout<<"Derived::non_virtual_Test()"<<endl;

         }

         void Delete()

         {

                   cout<<"Derived::Delete()"<<endl;

         }

         ~D()

         {

                   Delete();

         }

};

 

int main()

{

         B *b = new D();

         b->Func();

         b->Func1();

         delete b;

         getchar();

         return 0;

}

 

运行结果如下:

Base::init()

Derived::init()

Derived::Func()

Derived::virtual_Test()

Derived::non_virtual_Test()

Base::Func1()

Derived::virtual_Test()

Base::non_virtual_Test()

Base::Delete()

 

下面开始一一解释:

1B *b = new D();

此句的执行结果为:

Base::init()

Derived::init()

这个很容易明白,构造一个对象的时候,最先执行的就是最“上”的那个基类。也就是如果你的类是派生而来,首先执行的构造函数就是基类的构造函数,基类如果也是派生类,一样也要先执行派生类的构造函数,所以这里先执行Base再执行Derived

2b->Func();

此句的执行结果为:

Derived::Func()

Derived::virtual_Test()

Derived::non_virtual_Test()

首先,先让大家知道什么是静态绑定,什么是动态绑定。很简单,举个例子说明。

D *pD = new D(); 静态类型是*D,动态类型是*D

B *pB = pD; 静态类型是*B,即定义的类型;动态类型为*D,即所指向的类型

所谓静态绑定就是在编译期就确定的类型,如上所说的静态类型;动态绑定就是在运行期才确定的类型,如上所说的动态类型。

b->Func();因为Func()virtual函数,所以对象调用的是动态类型,也就Derived::Func()Func()函数里面又调用了两个函数virtual_Test()non_virtual_Test(),一样遵循上面的规制,virtual_Test()调用的是动态类型的Derived::virtual_Test(),而non_virtual_Test()调用的是Derived::Func()所属对象的Derived::non_virtual_Test()

3b->Func1();

此句的执行结果为:

Base::Func1()

Derived::virtual_Test()

Base::non_virtual_Test()

对于Func1()的执行也类似,Func1()non-virtual函数,所以调用对象调用的是静态类型的Base::Func1(),然后virtual_Test()调用的是动态类型的Derived:: virtual_Test(),而non_virtual_Test()调用的是Base::Func1()所属对象的Base::non_virtual_Test()

不近视的程序YUAN可能会发现Base构造函数中调用了virtual函数,按上面的规则,调用的应该是Derived::init()才对,是事实却是调用了Base::init()。这里要说明的就是这是特殊的情况,在构造函数中是没有多态的,这也符合常理,因为构造函数就是确定一个对象的内容的时候,那么对象都还确定,所以也就实现不了多态。

4delete b;

此句的执行结果为:

Base::Delete()

按照对象销毁的顺序,是跟构造的顺序相反的,也就是先销毁派生类的再销毁基类的,但这里没有调用~D()这个函数,等一下再说明原因。调用了~B()函数,~B()函数中调用了Delete()函数,它是一个virtual函数,遵循上面说到的规则,是执行~B()所属对象的Base::Delete()。为什么会没有执行到Derived的析构函数呢,我们看下面这则规则:C++明白指出,当derived class 对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义——实际执行时通常发生的是对象的derived成分没有被销毁。因为析构函数不是virtual的,所以并没有执行derived的析构函数,由此引申出:如果基类有virtual成员函数,就应该声明一个virtual的析构函数。这是好的编程习惯,有利于减少内存泄露。还有就是不要改变继承而来的non-virtual函数,这是不好的编程风格。

原文地址:https://www.cnblogs.com/littlethank/p/2313505.html