
C++多态
什么是多态?
多态的意思就是做同一件事情, 不同的对象产生不同的结果. 比如坐车的时候, 成人全票, 1.2以下免票.
其实函数重载也可以算作是多态的一种形式.
继承中的多态
函数重载我们已经讨论过了, 所以我们重点来看看在继承中如何实现多态.
构成多态的条件
在继承中构成多态需要满足两个条件:
1. 必须通过基类指针或者引用调用虚函数.
2. 被调用的必须是虚函数, 而且派生类中必须重写虚函数.
虚函数与虚函数重写
什么是虚函数?
被virtual修饰的函数就是虚函数
class Animal{
public:
virtual void func(){ //虚函数
cout<<"你不是人"<<endl;
}
};
class Person : public Animal{
virtual void func(){ //虚函数的重写
cout<<"你是人"<<endl;
}
};
虚函数的重写需要在派生类中完成, 而且派生类虚函数的返回值, 函数名称, 参数列表必须完全相同.
虚函数重写的特例
1.协变
协变的含义是派生类在重写虚函数时, 其返回值类型与基类虚函数返回值类型不同.
基类返回基类指针或引用, 派生类返回派生类指针或引用.
class A{};
class B:public A{};
class Animal{
public:
virtual A* func(){
cout<<"你不是人"<<endl;
return new A;
}
};
class Person : public Animal{
virtual B* func(){ //返回值类型不需要一定是Person*类型, 也就是说,
//只要返回值类型构成了继承, 就可以作为发生协变的返回值.
cout<<"你是人"<<endl;
return new B;
}
};
2.析构函数
如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。虽然函数名不相同,看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor。
class Person {
public:
virtual ~Person() {
cout << "~Person()" << endl;
}
};
class Student : public Person {
public:
virtual ~Student() {
cout << "~Student()" << endl;
}
};
// 只有派生类Student的析构函数重写了Person的析构函数,下面的delete对象调用析构函数,才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数。
纯虚函数与抽象类
在虚函数的后面写上 = 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;
}
};
void Test(){
Car* pBenz = new Benz;
pBenz->Drive();
Car* pBMW = new BMW;
pBMW->Drive();
}
函数重载和虚函数重写的区别
函数重载:
- 在同一作用域中
- 形参列表(参数个数 或 类型 或 顺序)必须不同
- 函数名相同
虚函数重写
- 必须是虚函数
- 函数名 参数列表 返回值必须相同
- 分别在基类和派生类的作用域

