C++分析——多态与虚函数 virtual

来源:互联网 发布:shopee123软件怎么样 编辑:程序博客网 时间:2024/06/07 12:48

  • C 虚函数的继承关系
    • 基类Test_virtual_A
    • 派生类Test_virtual_B
    • 派生类Test_virtual_C
    • 实现函数
      • Test_virtual_A类自己调用
      • Test_virtual_A类派生Test_virtual_B类
      • Test_virtual_A类派生Test_virtual_C类
      • Test_virtual_B类派生Test_virtual_C类
    • 析构虚函数
    • 纯虚函数
      • 带有纯虚函数的基类Test_virtual_A
      • 派生类Test_virtual_B
      • 派生类Test_virtual_C
    • 实现函数
      • Test_virtual_A类为指针指向Test_virtual_B类
      • Test_virtual_A类派生Test_virtual_C类
      • Test_virtual_B类为指针指向Test_virtual_C类
      • Test_virtual_C类自己创建对象

在类的函数前面加上 virtual即为虚函数,当基类的函数加上virtual时,表示该函数为虚函数,当子类对父类进行继承的时候,可以直接利用父类的虚函数的方法,也可以自己重新编写该函数的方法。

C++ 虚函数的继承关系

只有在父类的函数定义成为了虚函数后,子类才可以对该函数的功能进行改写,如同同类里的重载一样,不过不需要有传参类型不同的限制。没有加虚函数符号的函数只能使用父类现有的方法。

虚函数的源码示例

基类:Test_virtual_A

class Test_virtual_A{public:    Test_virtual_A()    {        std::cout << __func__ << " Init " << std::endl;    }           virtual ~Test_virtual_A()    {        std::cout << __func__ << " close" << std::endl;    }    void Test_func1()    {        std::cout << "Test_virtual_A " << __func__ << std::endl;    }    virtual void Test_func2()    {        std::cout << "Test_virtual_A " << __func__ << std::endl;    }    void Test_func3()    {        std::cout << "Test_virtual_A " << __func__ << std::endl;    }    void Test_func4()    {        std::cout << "Test_virtual_A " << __func__ << std::endl;    }       };

派生类Test_virtual_B

class Test_virtual_B : public Test_virtual_A{public:    Test_virtual_B()    {        std::cout << __func__ << " Init " << std::endl;    }           ~Test_virtual_B()    {        std::cout << __func__ << " close" << std::endl;    }    void Test_func1()    {        std::cout << "Test_virtual_B " << __func__ << std::endl;    }    void Test_func2()    {        std::cout << "Test_virtual_B " << __func__ << std::endl;    }    virtual void Test_func3()    {        std::cout << "Test_virtual_B " << __func__ << std::endl;    }   };

派生类Test_virtual_C

class Test_virtual_C : public Test_virtual_B{public:    Test_virtual_C()    {        std::cout << __func__ << " Init " << std::endl;    }           ~Test_virtual_C()    {        std::cout << __func__ << " close" << std::endl;    }    void Test_func1()    {        std::cout << "Test_virtual_C " << __func__ << std::endl;    }    void Test_func2()    {        std::cout << "Test_virtual_C " << __func__ << std::endl;    }};

实现函数

Test_virtual_A类自己调用

    Test_virtual_A *p = new Test_virtual_A;    p->Test_func1();    p->Test_func2();    p->Test_func3();    p->Test_func4();    delete p;    p = NULL;

执行结果

Test_virtual_A Init Test_virtual_A Test_func1Test_virtual_A Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_A close

Test_virtual_A类派生Test_virtual_B类、

    Test_virtual_A *sp = new Test_virtual_B;    sp->Test_func1();    sp->Test_func2();    sp->Test_func3();    sp->Test_func4();    delete sp;    sp = NULL;

执行结果

Test_virtual_A Init Test_virtual_B Init Test_virtual_A Test_func1Test_virtual_B Test_func2   //虚函数体现Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_B close~Test_virtual_A close

对于来Test_virtual_B类说,自己virtual void Test_func3()声明为虚函数,但在其继承的父类Test_virtual_A中不是虚函数,因此只能使用父类Test_virtual_A的方法。

Test_virtual_A类派生Test_virtual_C类

    Test_virtual_A *rp = new Test_virtual_C;    rp->Test_func1();    rp->Test_func2();    rp->Test_func3();       rp->Test_func4();    delete rp;    rp = NULL;

执行结果

Test_virtual_A Init Test_virtual_B Init Test_virtual_C Init Test_virtual_A Test_func1Test_virtual_C Test_func2   //虚函数体现Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close

Test_virtual_B类派生Test_virtual_C类

    Test_virtual_B *tp = new Test_virtual_C;    tp->Test_func1();    tp->Test_func2();    tp->Test_func3();       tp->Test_func4();    delete tp;    tp = NULL;

执行结果

Test_virtual_A Init Test_virtual_B Init Test_virtual_C Init Test_virtual_B Test_func1Test_virtual_C Test_func2   //虚函数体现Test_virtual_B Test_func3   //虚函数体现Test_virtual_A Test_func4~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close

在基类Test_virtual_A中,只有函数virtual void Test_func2()被定义为虚函数,继承的类Test_virtual_B中,函数Test_func2没有定义虚函数的符号,但Test_virtual_B派生出的Test_virtual_C的Test_func2函数却实现了虚函数的特点,因此基类声明的虚函数,即使不再使用virtual虚函数关键字修饰该函数,在其派生类中也是虚函数。虚函数有多重继承的关系。 由于虚函数具有多重继承的关系,虽然可以在派生类中间定义虚函数,但会打乱函数的关联性,因此尽量在基类就订好哪个函数是虚函数,为后面的派生类进行规划。

析构虚函数

在上一节的Test_virtual_A中,虚构函数也被定义为虚函数virtual ~Test_virtual_A(),若没有定义为虚函数,那么上面的运行就会变成以下结果。

$ ./project.o Test_virtual_A Init Test_virtual_A Test_func1Test_virtual_A Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_A closeTest_virtual_A Init Test_virtual_B Init Test_virtual_A Test_func1Test_virtual_B Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_A close          // Test_virtual_A类派生Test_virtual_B类Test_virtual_A Init Test_virtual_B Init Test_virtual_C Init Test_virtual_A Test_func1Test_virtual_C Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_A close          //Test_virtual_A类派生Test_virtual_B类Test_virtual_A Init Test_virtual_B Init Test_virtual_C Init Test_virtual_B Test_func1Test_virtual_C Test_func2Test_virtual_B Test_func3Test_virtual_A Test_func4~Test_virtual_B close          //Test_virtual_A类派生Test_virtual_B类~Test_virtual_A close$

类结束后没有调用自身的析构函数,而是只调用了继承的父类的析构函数,所以需要在析构函数中加上virtual。

纯虚函数

父类定义的虚函数还可以有自己的实现方法,但如果定义为纯虚函数,则将方法去掉,只定义方法的接口,方法的实现完全由所派生的子类去实现,因此其本身不能被直接调用,只能被继承,本身作为一个接口规范去派生子类。因此在写纯虚函数的基类的时候尽量将所有的方法都写成纯虚函数,纯粹作为一个接口的定义标准。
修改上一节的Test_virtual_A类,将Test_func1定义为虚函数,虚函数写法:
virtual void Test_func1() = 0;

基类函数Test_virtual_A如下所示,与上一节不同的是,这个类添加了带参数的构造函数。

带有纯虚函数的基类Test_virtual_A

class Test_virtual_A{public:    Test_virtual_A()    {        std::cout << __func__ << " Init " << std::endl;    }    Test_virtual_A(int a,int b)    {        std::cout << __func__ << " Init a = " << a << " b = " << b << std::endl;    }    virtual ~Test_virtual_A()    {        std::cout << __func__ << " close" << std::endl;    }    virtual void Test_func1() = 0;    virtual void Test_func2()    {        std::cout << "Test_virtual_A " << __func__ << std::endl;    }    void Test_func3()    {        std::cout << "Test_virtual_A " << __func__ << std::endl;    }    void Test_func4()    {        std::cout << "Test_virtual_A " << __func__ << std::endl;    }       };

派生类Test_virtual_B

这个类有两个继承

class Test_virtual_B : public Test_virtual_A,public Test_inline{public:    Test_virtual_B():Test_virtual_A(3,5),Test_inline(6,7)    {        std::cout << __func__ << " Init " << std::endl;    }    Test_virtual_B(int a,int b):Test_virtual_A(a,b),Test_inline(a,b)    {        std::cout << __func__ << " Init a = " << a << " b = " << b << std::endl;    }    ~Test_virtual_B()    {        std::cout << __func__ << " close" << std::endl;    }    void Test_func1()    {        std::cout << "Test_virtual_B " << __func__ << std::endl;    }    void Test_func2()    {        std::cout << "Test_virtual_B " << __func__ << std::endl;    }    virtual void Test_func3()    {        std::cout << "Test_virtual_B " << __func__ << std::endl;    }   };

派生类Test_virtual_C

与上一节不同的是,这次去掉对Test_func1的重载。

class Test_virtual_C : public Test_virtual_B{public:    Test_virtual_C():Test_virtual_B(5,6)    {        std::cout << __func__ << " Init " << std::endl;    }    Test_virtual_C(int a,int b):Test_virtual_B(a,b)    {        std::cout << __func__ << " Init a = " << a << " b = " << b << std::endl;    }    ~Test_virtual_C()    {        std::cout << __func__ << " close" << std::endl;    }    void Test_func2()    {        std::cout << "Test_virtual_C " << __func__ << std::endl;    }};

实现函数

Test_virtual_A类为指针指向Test_virtual_B类。

    Test_virtual_A *sp = new Test_virtual_B(15,36);    sp->Test_func1();    sp->Test_func2();    sp->Test_func3();    sp->Test_func4();    delete sp;    sp = NULL;

执行结果

$ ./project.o Test_virtual_A Init a = 15 b = 36Test_virtual_B Init a = 15 b = 36Test_virtual_B Test_func1Test_virtual_B Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_B close~Test_virtual_A close$

Test_virtual_A类派生Test_virtual_C类。

    Test_virtual_A *rp = new Test_virtual_C;    rp->Test_func1();    rp->Test_func2();    rp->Test_func3();       rp->Test_func4();    delete rp;    rp = NULL;

执行结果

$ ./project.o Test_virtual_A Init a = 5 b = 6Test_virtual_B Init a = 5 b = 6Test_virtual_C Init Test_virtual_B Test_func1Test_virtual_C Test_func2Test_virtual_A Test_func3Test_virtual_A Test_func4~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close$

Test_virtual_B类为指针指向Test_virtual_C类

    Test_virtual_B *tp = new Test_virtual_C(49,68);    tp->Test_func1();    tp->Test_func2();    tp->Test_func3();       tp->Test_func4();    cout << "Max is " << tp->Max() << endl;cout << "Min is " << tp->Min() << endl;    delete tp;    tp = NULL;

执行结果

$ ./project.o Test_virtual_A Init a = 49 b = 68Test_virtual_B Init a = 49 b = 68Test_virtual_C Init a = 49 b = 68Test_virtual_B Test_func1Test_virtual_C Test_func2Test_virtual_B Test_func3Test_virtual_A Test_func4Max is 68Min is 49~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close$

Test_virtual_C类自己创建对象

    Test_virtual_C *cp = new Test_virtual_C(57,98);    cp->Test_func1();    cp->Test_func2();    cp->Test_func3();    cp->Test_func4();    cout << "Max is " << cp->Max() << endl;    cout << "Min is " << cp->Min() << endl;    delete cp;    cp = NULL;

执行结果

$ ./project.o Test_virtual_A Init a = 57 b = 98Test_virtual_B Init a = 57 b = 98Test_virtual_C Init a = 57 b = 98Test_virtual_B Test_func1Test_virtual_C Test_func2Test_virtual_B Test_func3Test_virtual_A Test_func4Max is 98Min is 57~Test_virtual_C close~Test_virtual_B close~Test_virtual_A close$
原创粉丝点击