目录
一、多态的概念
1、问题的引出
2、多态的概念
3、多态的原理
4、虚析构函数
二、动态类型识别
1、问题的引出
2、dynamic_cast关键字用法
3、typeid关键字
三、纯虚函数
一、多态的概念
1、问题的引出
基类的指针指向派生类对象,在访问函数(基类与派生类的同名函数)时,只能调用基类的函数。
如何才能通过基类指针调用派生类函数?
#includeusing namespace std; class Parent { public: void show() { cout<<"this is Parent"< show(); //静态联编,编译器根据p1的类型(parent *)调用Parent里面的show函数 return 0; //却不能按我们期望的那样,调用派生类函数 }
2、多态的概念
在基类指针指向基类对象的时候,按照基类的方法做事,在指向派生类对象的时候,就按照派生类对象的方法做事,换句话说,基类指针可以根据指向的不同,既可以按照基类的方法做事 也可以按照派生类方式做事,它有多种形态,或者多种表现方式,这种现象称之为多态。
多态产生的条件:
1.要有继承
2.要有虚函数重写(发生在不同的作用域中,函数原型相同)
3.基类指针指向派生类对象
#includeusing namespace std; class Parent { public: virtual void show() //被virtual修饰的函数称为虚函数 { cout<<"this is Parent"< show(); //动态联编:运行的时候才知道p1指向什么对象 delete p1; p1 = new Parent; p1->show(); return 0; }
3、多态的原理
#includeusing namespace std; class Parent { public: int a; virtual void show() //被virtual修饰的函数称为虚函数 { cout<<"this is Parent"< show(); //通过指针找到对象,通过对下个前8个字节找到虚函数表, //通过虚函数表来找对应的函数(效率低),不要将所有的函数都声明为虚函数 return 0; }
4、虚析构函数
根据析构的规则,只能从当前基类往上调用析构函数,并不能调用子类的析构函数,通过将基类中的析构函数声明为虚析构,使得其能按照正确的顺序进行动态的释放对象。
#includeusing namespace std; class Parent { public: int a; Parent() { cout<<" Parent的构造函数"< show(); delete p; return 0; }
二、动态类型识别 1、问题的引出
(1)新的关键词:dynamic_cast
(2)dynamic_cast用于基类和派生类之间的转换
(3)dynamic_cast要求使用的目标类型是多态的
所以说: 要求至少有一个虚函数
用于指针转换时,转换失败返回NULL指针
用于引用转换时,转换失败引发bad_cast异常
#includeusing namespace std; class Parent { private: int a; public: enum {ID = 0}; virtual int GetID() { return ID; } }; class Child:public Parent { public: enum {ID = 1}; virtual int GetID() { return ID; } }; void f(Parent *p) { if(p->GetID() == Child::ID) //如果成立,说明指向派生类对象,没有任何转化过程 { Child *c = (Child *)p; //进一步将p指针转化为c型指针 cout<<"可以转换"< 2、dynamic_cast关键字用法
该关键字主要用于基类与派生类之间的类型转换。
#includeusing namespace std; class Parent { private: int a; public: virtual void show(){}; }; class Child:public Parent { public: enum {ID = 1}; virtual void show(){}; }; void f(Parent *p) { Child *c = dynamic_cast (p); //可用dynamic_cast直接转换类型 if(NULL == c) //转换失败,会返回NULL { cout<<"转换失败"< 3、typeid关键字
typeid运算符用来获取一个表达式的类型信息
typeid的操作对象可以是表达式,也可以是数据类型
typeid(expression) 或者 typeid(datatype)
#include#include using namespace std; class Parent { private: int a; public: virtual void show(){}; }; class Child:public Parent { public: enum {ID = 1}; virtual void show(){}; }; void f(Parent *p) { if(typeid(*p) == typeid(Child)) //说明指针p指向Child。可以进行类型转换 { cout<<"转换成功"< 三、纯虚函数
格式:virtual 返回值类型 函数名 (函数参数) = 0;
含有纯虚函数的类称为抽象类,抽象类不能定义实例对象。
#includeusing namespace std; class Parent { private: int a; public: virtual void show() = 0; //纯虚函数,没有函数体 }; class Child:public Parent { public: virtual void show() { cout<<"this is child!"< show(); return 0; }



