1 虚函数相关知识
1.1 虚函数概念
1.定义:在一个类的成员函数前面加上virtual关键字,则该函数就称为虚函数。
2.如果一个函数不是类的成员函数,则该函数不能定义为虚函数。(即就是类外面不能使用virtual关键字)
- 虚函数中有一个特殊的虚函数:纯虚函数
1.2 纯虚函数与抽象类
1.纯虚函数:在虚函数的后面加上=0;
virtual void Display() = 0;
2.包含纯虚函数的类称为抽象类,抽象类不能实例化出对象;
3.如果一个类继承了抽象类,则该类也变成了抽象类(因为这个类继承了抽象类里面的纯虚函数),如果该派生类想实例化出对象,则该派生类必须重写这个纯虚函数;重写之后父类仍然不能实例化出对象,只有子类才可以。所以将抽象类称为接口类,保证了只要将父类的虚函数定义成纯虚函数,则其子类必须重写这个虚函数。
例如:Student类重写了Person类的虚函数Display,则子类可以示例化出对象。
2 多态
1.多态就是多种形态;
2.多态的分类:静态多态和动态多态
2.1 静态多态
在系统编译期间就可以确定程序执行到当前位置需要执行哪个函数,例如C++中的函数重载与泛型编程就属于静态多态。
2.2 动态多态
在系统编译期间并不确定该程序需要执行哪个函数,只有在程序运行时才确定执行哪个函数。C++采用虚函数实现动态多态。
2.3 多态的构成条件
①父类对象的指针或引用;
②虚函数的重写。
2.3.1 重写
在不同的作用域下(一个在父类一个在子类)两个函数的函数名,参数,返回值完全相同(协变除外)。
- 协变:父类和子类的两个虚函数,函数名相同,参数也相同,但返回值一个返回父类对象的指针(或引用),一个返回子类对象的指针(或引用)
构成协变的代码:
class AA
{
public:
virtual AA* fun1()
{
cout << "AA::fun1()" << endl;
return this;
}
private:
int _a;
};
class BB :public AA
{
public:
virtual BB* fun1()
{
cout << "BB::fun1()" << endl;
return this;
}
private:
int _b;
};
int main()
{
AA a;
BB b;
AA* p = &a;
p->fun1();
p = &b;
p->fun1();
system("pause");
return 0;
}
2.4 构成多态的示例:
class Person
{
public:
virtual void BuyTicket()
{
cout << "买票--全价" << endl;
}
protected:
string _name;
};
class Student :public Person
{
public:
virtual void BuyTicket()
{
cout << "买学生票--半价" << endl;
}
protected:
int _num;
};
int main()
{
Person* p;
Person a;
Student s;
p = &a;
p->BuyTicket(); //指向父类,调用父类的函数
p = &s; //切片行为 ,指向子类,调子类的函数
p->BuyTicket();
system("pause");
return 0;
}
运行结果如下:
2.5 不构成多态的场景:
场景1:没有虚函数的重写
class Person
{
public:
void BuyTicket() //由于父类没有加上virtual关键字,不构成虚函数重写
{
cout << "买票--全价" << endl;
}
protected:
string _name;
};
class Student :public Person
{
public:
void BuyTicket()
{
cout << "买学生票--半价" << endl;
}
protected:
int _num;
};
int main()
{
Student s;
s.BuyTicket(); //因为Person类和Student类中有同名的Display函数,这个函数两个类中都没有加上virtual关键字,构成覆盖,就只会调用子类的BuyTicket函数。
system("pause");
return 0;
}
场景2:没有父类对象的指针或引用
class Person
{
public:
virtual void BuyTicket()
{
cout << "买票--全价" << endl;
}
protected:
string _name;
};
class Student :public Person
{
public:
virtual void BuyTicket()
{
cout << "买学生票--半价" << endl;
}
protected:
int _num;
};
int main()
{
Person p; //构成多态与对象有关,指向什么对象,就调用那个对象改写的虚函数,不构成多态与类型有关
p.BuyTicket(); //没有父类对象的指针或引用,不构成多态则与类型有关,它是Person类的,则调用Person类的BuyTicket函数
Student s;
s.BuyTicket(); //它是Student类的,则调用Student类的BuyTicket函数
system("pause");
return 0;
}