今天给大家分享面向对象三个特性-多态。在C++中多态也是一个很复杂的内容。作为面向对象三个特性,值得我们深入学习。
多态的概念
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
多态的实现
多态是在继承的基础之上去实现的,只有父类和子类的关系才能实现多态。父类和子类实现多态的前提条件是定义虚函数。
那么在继承中要构成多态还有两个条件:
- 必须通过基类的指针或者引用调用虚函数
- 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
class Person {
public:
//虚函数
virtual void BuyTicket() {
cout << "买票-全价" << endl;
}
virtual ~Person()
{
cout << "~Person()" << endl;
}
};
class Student : public Person {
public:
virtual void BuyTicket() {
cout << "买票-半价" << endl;
}
~Student()
{
cout << "~Student()" << endl;
}
};
void Func(Person* p)//使用指针析构函数必须写成虚函数,否则不会正确调用虚构函数
{
p->BuyTicket();
delete p;
}
int main() {
Func(new Person());
Func(new Student());
return 0;
}
重载、重写(覆盖)、重定义(隐藏)的区别
C++中的final和override
final用来修饰虚函数的,表示此虚函数不能被重写。
override用来检查是否重写了,基类的虚函数,如果没有就会报错。
抽象类
在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。
这就是接口的定义方式。
class Person {
public:
virtual void BuyTicket() = 0;
};
设计抽象类(通常称为 ABC)的目的,是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。
多态的原理
我们首先思考一下为什么这个类是8个字节。
这个通过监视窗口就可以看出来,本人用的IDE是vs2019。
在per对象中有一个vfptr,这个是一个虚表,用来存放类中所有虚函数的指针的一张表。
看上图可以看出只有虚表内只会存放虚函数的地址,普通的成员函数并不会存放进去。
我们可以看到上图中,子类和父类各有一张虚表,重写虚函数之后,子类和父类的成员函数地址是不一样的。所以才能通过调用父类的指针或引用实现多态。没有重写的sleep成员函数,和父类的函数地址是一样的。
这就是多态的特点和原理,希望对您有所帮助。