C++的多态性概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数
1:用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。
2:存在虚函数的类都有一个一维的虚函数表叫做虚表,类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的。
3:多态性是一个接口多种实现,是面向对象的核心,分为类的多态性和函数的多态性。
4:多态用虚函数来实现,结合动态绑定.
5:纯虚函数是虚函数再加上 = 0;
6:抽象类是指包括至少一个纯虚函数的类。
纯虚函数:virtual void fun()=0;即抽象类!必须在子类实现这个函数,即先有名称,没有内容,在派生类实现内容。
#include <iostream>
using namespace std;
class Animal
{
public:
Animal(int value = 0)
:Adata(value)
{
cout << "A : " << value << endl;
}
//Animal() { cout << "AAA" << endl; } //不带参数的构造函数
virtual ~Animal() //!!!!!虚析构函数,否则子类的析构函数不会被调用
{
cout << "~A : " << Adata << endl;
}
virtual void f()
{
cout << "A f" << endl;
}
void ff()
{
cout << "A ff" << endl;
}
private:
int Adata;
};
class Cat : public Animal
{
public:
Cat(int v = 0)
:Animal(v), t(v) //父类构造函数有参数,子类构造的时候需对父类进行初始化
{
cout << "C : " << v << endl;
}
virtual ~Cat() //子类可以虚析构也可以不虚析构
{
cout << "~C : " << t << endl;
}
void f()
{
cout << "Cat f" << endl;
}
void ff()
{
cout << "Cat ff" << endl;
}
private:
int t;
};
int main()
{
//Animal *ani = new Animal; //创建指针new一个对象
//ani->Shout();
//delete ani;
//Animal ani; //直接创建一个对象
//ani.Shout();
//Cat cat;
//cat.f();
//Animal badCat = Cat();
//badCat.Shout();
Animal *pa = new Cat(1);
pa->f();
delete pa;
Cat cc(2);
system("pause");
}
总结(基类有虚函数的):
1:每一个类都有虚表
2:虚表可以继承,如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,只不过这个地址指向的是基类的虚函数实现,如果基类有3个虚函数,那么基类的虚表中就有三项(虚函数地址),派生类也会虚表,至少有三项,如果重写了相应的虚函数,那么虚表中的地址就会改变,指向自身的虚函数实现,如果派生类有自己的虚函数,那么虚表中就会添加该项。
3:派生类的虚表中虚地址的排列顺序和基类的虚表中虚函数地址排列顺序相同。
这就是c++中的多态性,当c++编译器在编译的时候,发现Father类的Say()函数是虚函数,这个时候c++就会采用晚绑定技术,也就是编译时并不确定具体调用的函数,而是在运行时,依据对象的类型来确认调用的是哪一个函数,这种能力就叫做c++的多态性,我们没有在Say()函数前加virtual关键字时,c++编译器就确定了哪个函数被调用,这叫做早期绑定。
c++的多态性就是通过晚绑定技术来实现的。
c++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数,如果对象类型是派生类,就调用派生类的函数,如果对象类型是基类,就调用基类的函数。