多态是指使用相同的函数名来访问函数不同的实现方法,即“一种接口,多种方法”,用相同的形式访问一组通用的运算,每个运算可能对应的行为不同。
C++支持编译时多态和运行时多态,运算符重载和函数重载就是编译时多态,而派生类和虚函数实现运行时多态。
1、运行时多态:
class A
{
public:
virtual void play()
{
cout<< "A:play"<<endl;
}
};
class B : public class 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;
}
自行查看运行结果 分析;
2、纯虚函数
纯虚函数的定义形式为 virtual void play() = 0;含有纯虚函数的类是不能实例化的,纯虚函数相当于接口,需要在派生类中实现函数;含有纯虚函数的类被叫做抽象类;在项目中纯虚函数的实践:
class Base_Test
{
void play()
{
cout<<"Base_Test:play"<<endl;
}
};
class Base
{
virtual void play() = 0;
virtual Base_Test test() = 0;
};
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;
}
};
输出为:
由此可以看出虚基类的用法;