多态性总结
- 多态性是C++语言最重要的基本特征之一
- 正是因为多态性的灵活,才使之如此重要,也需要仔细思考才能很好把握
概念
多态(polymorphism)/动态绑定使编译器能够在运行时决定使用基类中定义的函数还是派生类中定义的函数
要素
- 虚函数的前提是有基类及其派生类
- 在基类中要有虚函数的定义: 成员函数的virtual声明. 因为默认不使用动态函数
- 必须通过基类类型的指针或者引用进行函数调用
示例
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Base
{
public:
virtual string print() const
{
cout<<"Base"<<endl;
return "Base";
}
};
class Derived : public Base
{
public:
string print() const
{
cout<<"Derived"<<endl;
return "Derived";
}
};
void append(const Base & ba)
{
cout<<"haha0\n";
ba.print();
}
int main()
{
Base b1;
Derived d1;
Base *b2 = &b1;
Derived & d2 = d1;
append(b1); //Base
append(*b2); //Base
append(d1); //Derived
append(d2); //Derived
return 0;
}
- 基类定义了虚函数virtual print(), 并在派生类中重定义
- 定义了一个外部函数append(),其参数为基类对象的引用; 在函数体内基类对象参数调用了虚函数.
- 主函数中append()的实参分别为基类对象\基类对象的指针\派生类对象\派生类对象的引用. 结果:基类对象及指针调用的是基类中的print();派生类对象及引用调用的是派生类的print(), 即使append()的形参不是派生类
几个关键问题
- 派生类中一般需要重定义所继承的虚函数,若没有则使用基类版本
- 一旦函数被声明为虚函数,则派生中一直为虚函数;派生类中可以使用关键字virtual,也可以不保留
- 虚函数重定义时候,原型不能变:返回类型、形参数目和类型都不能更改;若不一致则为重载
- 构造(三大类)函数不能做为虚函数,静态成员函数不能定义为虚函数
在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定
静态的数据成员被所有的对象共享,静态数据成员不属于对象,而是属于类的;静态成员函数也是属于类的,它没有this指针,它无法进行对象的判别 - 构造及析构函数体内切勿使用虚函数
在进行基类成员构造的时候对象就被编译器视为基类类型;派生类部分的成员还没有初始化,想调用派生类的虚函数相当于要去使用未定义的数据;另外,若此时涉及到调用虚函数,也是基类的虚函数,是不可能正确实现多态的
析构函数同理 - 虚析构函数
虚析构函数是根据对象的类型来动态释放基类/派生类的对象的
意味着可以用基类的引用释放派生类的对象的空间
当基类中有虚函数时,最好将析构函数也声明为虚函数 - 虚函数的屏蔽
作用域符号 : : 可以强制调用指定的虚函数,因为派生类的对象可以赋值给基类,传入派生类对象依然可以执行基类定义的虚函数 - 纯虚函数
纯虚函数是用来被继承的;纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。凡是含有纯虚函数的类叫做抽象类。这种类不能声明对象,只是作为基类为派生类服务
1056

被折叠的 条评论
为什么被折叠?



