• 一道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函数,这是不好的编程风格。

  • 相关阅读:
    省选测试28
    省选测试27
    省选测试26
    省选测试25
    省选测试24
    省选测试23
    省选测试22
    省选测试21
    关于maven 导入依赖的最终处理问题
    Dubbo 2 之抽取公共接口
  • 原文地址:https://www.cnblogs.com/littlethank/p/2313505.html
Copyright © 2020-2023  润新知