zoukankan      html  css  js  c++  java
  • 继承中的虚函数、纯虚函数、普通函数

    一、虚函数

             被virtual关键字修饰的类成员函数就是虚函数。虚函数的作用就是实现运行时的多态性,将接口与实现分离。简单理解就是相同函数有着不同的实现,但因个体差异而采用不同的策略。

             基类中提供虚函数的实现,为派生类提供默认的函数实现。派生类可以重写基类的虚函数以实现派生类的特殊化。如下:

    class Base{

    public:

            virtual void foo() { cout<<"Base::foo() is called"<<endl; }

    };

    class Derived : public Base {

    public:

            void foo() { cout<<"Derived::foo() is called"<<endl; }

    };


    int main(void)

    {

           Base *b = new Derived();

           b->foo(); // b虽然是类型Base的指针 但是实际上指向的是Derived类 所以调用的函数foo是Derived类的

           return 0;

    }


    二、纯虚函数

            纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加"=0"。

            包含纯虚函数的类被称为“抽象类”,抽象类不能实例化成对象,但是可以定义抽象类的引用和指针。此外,实现了该纯虚函数的派生类可以实例化成对象。

    class A
    {
    public:
            virtual void out1(string s)=0;
            virtual void out2(string s)
           {
               cout<<"A(out2):"<<s<<endl;
           }
    };


    三、普通函数

    普通函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数。

    普通函数是基类为派生类提供的“强制实现”。

    因此,在继承关系中,派生类不应该重写基类的普通函数,因为函数的调用只与类对象的字面值有关。下面是搬来的一段代码:

    #include <iostream>
    using namespace std;

    class A
    {
    public:
         virtual void out1()=0;  ///由子类实现
         virtual ~A(){};
         virtual void out2() ///默认实现
         {
             cout<<"A(out2)"<<endl;
         }
         void out3() ///强制实现
         {
             cout<<"A(out3)"<<endl;
         }
    };

    class B:public A
    {
    public:
         virtual ~B(){};
         void out1()
         {
             cout<<"B(out1)"<<endl;
         }
         void out2()
         {
             cout<<"B(out2)"<<endl;
         }
         void out3()
         {
             cout<<"B(out3)"<<endl;
         }
    };

    int main()
    {
         A *ab=new B;
         ab->out1();
         ab->out2();
         ab->out3();
         cout<<"************************"<<endl;
         B *bb=new B;
         bb->out1();
         bb->out2();
         bb->out3();

        delete ab;
         delete bb;
         return 0;
    }



    执行结果:

    B<out1>

    B<out2>

    A<out3>

    *****************************************

    B<out1>

    B<out2>

    B<out3>


    四、虚函数与构造函数和析构函数

          1) 当存在类继承并且析构函数中有必须要进行的操作时(如需要释放某些资源,或执行特定的函数)析构函数需要是虚函数,否则若使用父类指针指向子类对象,在delete时只会调用父类的析构函数,而不能调用子类的析构函数,从而造成内存泄露或达不到预期结果;

        2) 构造函数不能为虚函数:构造函数在进行调用时还不存在父类和子类的概念,父类只会调用父类的构造函数,子类调用子类的,因此不存在动态绑定的概念;但是构造函数中可以调用虚函数,不过并没有动态果,只会调用本类中的对应函数;

           3) 静态成员函数不能为虚函数:静态成员函数是以类为单位的函数,与具体对象无关,虚函数是与对象动态绑定的。


    这篇博客介绍的比较详细,我就不搬了……


    参考文献:

         1> C++ 虚函数表解析

         2> C++ 在继承中虚函数、纯虚函数、普通函数,三者的区别

         3> C++里神奇的虚函数

         4> 虚函数实现机制、构造函数、析构函数能否为虚函数,与纯虚函数

  • 相关阅读:
    springboot+maven+thymeleaf配置实战demo
    报错AbstractStandardExpressionAttributeTagProcessor
    IllegalStateException: Unable to find a @SpringBootConfiguration
    Java装饰模式
    Java容器类解析
    jdk之object源码理解
    osx brew mysql
    java String[] 初始化
    date 常用
    mac mysql
  • 原文地址:https://www.cnblogs.com/Lilu-1226/p/10776873.html
Copyright © 2011-2022 走看看