目录
一、多态的概念
二、多态的定义及实现
1、多态的构成条件
2、虚函数
3、虚函数的重写
3.1、协变:
3.2、析构函数重写:
4、override 和 final 关键字
5、重载、覆盖、隐藏
三、抽象类
1、接口继承
2、实现继承
一、多态的概念
顾名思义,多态就是多种形态,举个例子:比如说买票这个行为,当普通人买票时是全价票,学生买票时是半价票,军人买票时是优先买票。也就是说一件事,每个不同的类去做,会发生不一样的行为称之为多态。
二、多态的定义及实现
1、多态的构成条件
1、多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如 Student 继承了Person。 Person 对象买票全价, Student 对象买票半价。2、必须通过基类的指针或者引用调用虚函数。3、被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。

2、虚函数
虚函数就是被virtual修饰的类成员函数成为虚函数。
class Person{
public:virtual void BuyTicket() {cout << "全价票" << endl;}
}
3、虚函数的重写
class Person {
public:virtual void BuyTicket(){cout << "买票-全价" << endl;}
};class Student : public Person {
public:virtual void BuyTicket(){cout << "买票-半价" << endl;}//void BuyTicket() { cout << "买票-半价" << endl}
};void Func(Person& p)
{p.BuyTicket();
}int main()
{Person ps;Func(ps);Student st; Func(st);return 0;
}
3.1、协变:
派生类重写基类虚函数时,与基类虚函数返回的类型不同。
3.2、析构函数重写:
如果基类的析构函数是虚函数,那么派生类的析构函数默认会和基类的析构函数构成重写,虽然函数名不同,但是编译器进行编译后,把析构函数统一处理为destructor。
class Person
{
public:virtual void BuyTicket(){cout << "全价" << endl;}virtual Person* F(){return new Person;}virtual ~Person(){cout << "~Person" << endl;}
};
class Student : public Person
{
public:virtual void BuyTicket(){cout << "半价" << endl;}virtual Student* F(){return new Student;}virtual ~Student(){cout << "~Student" << endl;}
};
void Test(Person& p)
{p.BuyTicket();
}
int main()
{Person p;Student s;Test(p);Test(s);return 0;
}析构了两次~Person
class Person {
public:~Person(){cout << "~Person()" << endl;}
};class Student : public Person {
public:~Student(){cout << "~Student()" << endl;}
};int main()
{Person* p1 = new Person;Person* p2 = new Student;delete p1;delete p2;return 0;
}
class Person {
public:virtual ~Person(){cout << "~Person()" << endl;}
};class Student : public Person {
public:virtual ~Student(){cout << "~Student()" << endl;}
};int main()
{Person* p1 = new Person;Person* p2 = new Student;delete p1;delete p2;return 0;
}
4、override 和 final 关键字
C++11中, 用来辅助进行虚函数多态的多种复杂情况,避免出现疏忽而导致错误的情况出现。
override : 检查派生类虚函数是否重写了基类的某个虚函数,如果没有就会报错。
class Person
{
public:/*virtual*/ void BuyTicket(){cout << "全价票" << endl;}
};
class Student : public Person
{
public:virtual void BuyTicket() override//报错{cout << "半价票" << endl;}
};
class Child : public Student
{
public:virtual void BuyTicket() override{cout << "半价票" << endl;}
};
final : 修饰虚函数,表示这个虚函数不能被重写。
class Person
{
public:virtual void BuyTicket(){cout << "全价票" << endl;}
};
class Student : public Person
{
public:virtual void BuyTicket() final{cout << "半价票" << endl;}
};
class Child : public Student
{
public:virtual void BuyTicket()//{cout << "半价票" << endl;}
};
5、重载、覆盖、隐藏
1.重载指的是,函数名在一个作用域,并且函数名相同,参数不同的情况,那么这两个函数就构成了函数重载,编译器在进行处理的时候会根据参数形成不同的函数表。
2.重写指的是,两个函数在基类和派生类的作用域下,前提是函数名、参数、返回值都一样的情况下,如果是虚函数,那么就构成了重写,其中子类可以不写virtual,可以理解为虚函数的属性被从基类中继承了下来,但是并不推荐这样写,其中要注意特殊情况,比如协变和析构函数的情况。
3.隐藏指的是,两个函数在基类和派生类的作用域下,当函数名相同的时候,如果不符合重写的定义那么就是重定义了,比如在继承中见到的很多种情况。
三、抽象类
抽象类的定义:在虚函数后面写上=0,就是纯虚函数,有纯虚函数的类就是抽象类,特点是不能实例化出一个具体的对象派生类也是不能,只有在重写了虚函数,才能实例化,纯虚函数体现了派生类要重写的这个原则,同时也体现了接口继承的概念。
基类 - 抽象类 - 不能实例化出对象
class Car
{
public:virtual void Drive() = 0; 纯虚函数,不需要实现它
};派生类
class Benz :public Car
{
public:virtual void Drive() 必须重写基类虚函数,派生类才能实例化出对象{cout << "Benz-舒适" << endl;}
};class BMW :public Car
{
public:virtual void Drive(){cout << "BMW-操控" << endl;}
};int main()
{基类是抽象类,不能实例化出对象,但可以定义基类指针,用来实现多态Car* pBenz = new Benz;pBenz->Drive();Car* pBMW = new BMW;pBMW->Drive();return 0;
}
1、接口继承
接口继承(Interface Inheritance)是指从一个纯虚基类(pure virtual base class)继承而来,目的是为了实现一个类的接口,使得派生类必须实现该接口中定义的所有纯虚函数。接口继承的主要目的是实现类的接口复用,它并不关心实现细节。在接口继承中,派生类只需要实现基类中定义的纯虚函数,不需要关心基类中其他的数据和函数。
class Shape
{
public:virtual void draw() = 0;//纯虚函数
};
class Cirrle : public Shape
{
public:void draw() override{//实现圆形的绘画}
};
class Squre : public Shape
{void draw() override{//实现矩形的绘画}
};
2、实现继承
实现继承(Implementation Inheritance)是指从一个普通的基类(非纯虚基类)继承而来,目的是为了实现基类中已有的函数或数据。实现继承的主要目的是实现代码复用,它关心基类中的实现细节。在实现继承中,派生类会继承基类中所有的成员函数和数据成员,并且可以重写这些函数以改变它们的行为。
class Person
{
public:virtual void Say(){cout << "Person" << endl;}
};
class Student : public Person
{
public:virtual void Say() override{cout << "Student" << endl;}
};int main()
{Person p;Student s;s.Say();return 0;
}
下章节介绍多态的原理!如有不正之处,希望大家私信我去改正!