c++中的虚函数

   多态是指使用相同的函数名来访问函数不同的实现方法,即“一种接口,多种方法”,用相同的形式访问一组通用的运算,每个运算可能对应的行为不同。


   C++支持编译时多态和运行时多态,运算符重载和函数重载就是编译时多态,而派生类和虚函数实现运行时多态。

   1、运行时多态:

class A
 {
  public:
     virtual  void play() 
     {
      cout<< "A:play"<<endl;
     }
  };

class B : public  A
 {
  public:
    void play()
     {
      cout<<"B: play"<<endl;
    }    
};

int main()
{
	A class_A;
	B class_B;
	A* p;
	p = &class_A;
	p -> play();
	p = &class_B;//父类指针指向子类对象
	p -> play();

	return 0;
}
 

  输出结果:

       A:play

       B:play

      虚函数实现多态,具体到这个例子,可以得出,多态性体现在父类指针可以指向子类对象,并且可以访问子类的成员函数。假设基类的成员函数不是虚函数,则输出结果是:

       A:play

       A:play 

2、纯虚函数      

纯虚函数的定义形式为 virtual void play() = 0;含有纯虚函数的类是不能实例化的,纯虚函数相当于接口,需要在派生类中实现函数;含有纯虚函数的类被叫做抽象类;在项目中纯虚函数的实践:

   

  class Base
  {
     public:
      virtual void play() = 0;
    };
class Base_Test : public Base {
public: void play()    { cout<<"Base_Test:play"<<endl;
   }
};

  

3、虚基类

      虚基类的引出主要是为了解决继承中的二义性问题,在多个派生类中,定义了同名函数,这时再在main函数里面通过基类调用该方法时,编译器就犯难了。因为它不知道你到底是想用哪一个派生类里面的方法。通过下面的例子来详细阐述:

      大家都知道C++是支持多重继承的,那么就会遇到这样一个问题。如果一个派生类的多个基类是从一个共同的基类派生出来的,那么这个派生类会出现多个最底层基类的拷贝,程序中如何分辨呢。虚基类是让基类只有一个拷贝,程序中就不会出现不确定性。虚基类在派生类中声明:格式如下:class 派生类名:virtual 继承方式 基类。

#include <iostream>
using namespace std;
class Base
{
public :
  Base()
  {
   cout<<"Base()"<<endl;
  }
~Base() { cout<<"~Base()"<<endl; } }; class Continuator1 : public Base { public: Continuator1() { cout<<"Continuator1()"<<endl; } ~Continuator1() { cout<<"~Continuator1()"<<endl; } }; class Continuator2 : public Base { public: Continuator2() { cout<<"Continuator2"<<endl; } ~Continuator2() { cout<<"~Continuator2()"<<endl; } }; class Continuator : public Continuator1,public Continuator2 { public: Continuator() { cout<<"Continuator()"<<endl; } ~Continuator() { cout<<"~Continuator()"<<endl; } private: Base base; }; int main() { Continuator c; return 0; }

  

这个例子的运行结果是:

      从构造函数调用的顺序可以看出,在声明Continuator 对象时。首先调用基类Continuator1的构造,调用Continuator1的构造时就要先调用Base的构造函数,然后再调用Continuator1的构造函数,然后调用Continuator2,再调用成员对象的构造函数初始化成员对象base;最后调用派生类Continuator1的构造函数。析构函数调用顺序和构造函数调用顺序相反。

      把Continuator1和Continuator2类的定义修改为:

class Continuator1 :virtual public Base
{
public:
Continuator1()
{
cout<<"Continuator1()"<<endl;
}
~Continuator1()
{
cout<<"~Continuator1()"<<endl;
}
};

class Continuator2 :virtual public Base
{
public:
Continuator2()
{
cout<<"Continuator2"<<endl;
}
~Continuator2()
{
cout<<"~Continuator2()"<<endl;
}
};

  

输出为:

  

由此可以看出虚基类的用法;

原文地址:https://www.cnblogs.com/nobbyoucanyouup/p/4593881.html