虚函数&多态

来源:互联网 发布:网络暴力调查报告配图 编辑:程序博客网 时间:2024/06/18 11:10

1.虚函数--类的成员函数前面加上virtual关键字,则这成员函数称为虚函数。

虚函数重写--当在子类中定义一个与父类完全相同的虚函数时,则称子类这个函数重写(也称覆盖)了父类的这个虚函数。

#include<iostream>using namespace std;class Person{public:virtual void BuyTickets() //父类的virtual不能省略{cout<<"买票"<<endl;}};class Student : public Person{public:virtual void BuyTickets() //虚函数重写{cout<<"买票半价"<<endl;}};int main(){Person p;Student s;Person *ptr; //父类的指针ptr = &p;  //父类对象赋给父类指针p.BuyTickets();ptr = &s;  //子类对象赋给父类指针s.BuyTickets();return 0;}
 首先,我们先看是否虚函数重写;在此处是虚函数重写。

其次,看是否是父类的指针或者引用;在此处是父类的指针。

所以,满足以上两点,构成多态,故在调用时按对象进行调用。

运行结果:


总结:

(1)子类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外)

(2)父类中定义了虚函数,在子类中该函数始终保持虚函数的特性。

(3)只有类的成员函数才能定义为虚函数。

(4)静态成员函数不能定义为虚函数。

(5)如果在类外定义虚函数,只能在声明函数时加上virtual 关键字,类外定义不能加上virtual。

(6)构造函数不能为虚函数,可以将operator=定义为虚函数,但最好不要,因为使用时容易引起混淆。

(7)不要在构造函数和析构函数里调用虚函数,在构造函数和析构函数对象是不完整的,可能会发生未定义的行为。

(8)最好把父类的析构函数声明为虚函数。

(这是为什么呢?析构函数比较特殊,因为子类析构函数和父类的析构函数的名称不一样,但是在这里构成覆盖,这里因为编译器做了特殊处理。把父类析构函数定义为虚函数,如果构成多态,则会按对象去调用,就不会造成内存泄露)。

2.纯虚函数--在成员函数的形参后面加上=0,则成员函数为纯虚函数。包含纯虚函数的类叫抽象类。纯虚函数不能实例化出对象。一般期望子类重写的函数定义为纯虚函数。

class Person{virtual void Display() = 0; //纯虚函数protected:string _name;  //姓名};class Student : public Person{};
3.友元与继承

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。

4.继承与静态成员

基类里面定义了static成员,则整个集成体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static实例。