本节知识点:
1.动态类型识别的前因:
a.首先我们先说类之间的几种强制类型转换: 第一、具有继承关系的类对象之间的转换(即子类对象与父类对象之间,或叫对象之间),由于赋值兼容性原则,child c1; parent p1 = c1; 子类是特殊的父类,因为子类是大于等于父类的,所以将子类对象赋值给父类对象,是安全的( 将大的赋值给小的是安全的,这样由于默认强制类型转换,不会造成访问到未知数据,造成未知错误 )。编译器会默认将子类中父类没有成员砍掉,这个过程就是强制类型转换的过程,其实是默认强制类型转换,所以可以省略parent p1 = (parent) c1; 或者 parent p1 = static_cast第二、 具有继承关系的类对象指针之间的转换(即子类对象指针与父类对象指针之间,或叫指针引用之间,因为引用实质上是一种指针),由于赋值兼容性原则,child* c1; parent* p1= c1;这个过程中隐藏了一个强制类型转换的过程,即parent* p1 = (parent*) c1; 或 parent* p1 = static_cast
第四、没有继承关系的类对象指针之间的转换,同样也是一点意义都没有的,也只能使用c方式的野蛮转换,test* t1 = NULL; child* c2 = (child*)t1; 示例代码:
#include注意:通过上面分析,出现了一个问题,就是在对象之间进行强制类型转换的时候,parent p1 = (parent) c1; 把子类对象赋值给父类对象的时候,把c1强制类型转换成为parent类型就可以了,但是当反过来,child c1 = (child&) p1; child c1 = static_cast#include using namespace std; class parent { public: int a; }; class child : public parent { public: int b; }; class test { }; int main() { child c1; c1.a = 10000; c1.b = 20000; child* cp1 = &c1; parent* pp1 = cp1; //由于赋值兼容性原则 所以默认强制类型转换 parent* pp2 = (parent*)cp1; //此语句与上面语句一样 parent* pp3 = static_cast (cp1); //此语句与上面语句一样 child* cp2 = (child*)pp1; cout << "cp2 " << cp2->a << " " << cp2->b << endl; child* cp3 = static_cast (pp1); cout << "cp3 " << cp3->a << " " << cp3->b << endl; /*没有继承关系的类之间的强制类型转换,只能用 c语言的方式,static_cast报错*/ /*因为没有继承关系的类之间的强制类型转换,无论是指针之间的,还是变量之间的,都没有意义*/ test* t1 = NULL; child* c2 = (child*)t1; // child* cc2 = static_cast (t1); test t2; child c3 = (child&)t2; // child c4 = static_cast (t2); return 0; }
2.动态类型:
a.由于基类指针可以直接指向派生类对象,因此可能存在指针所指类型与具体指向的对象类型不同的情况,如parent* p1 = &c1; 或者 parent* p1 = new child; 动态类型指的是基类指针所指向的对象的实际类型!即p1指向的到底是父类对象还是子类对象! 所以:动态类型导致,child *c2 = (child*) p1; 这样的语句不知道是否正确,当p1的动态类型为child时,(child* )p1强制类型转换成功,否则,可能出现无法预知的错误!即基类指针是否可以强制类型转换为子类指针取决于动态类型!3.动态类型的识别(多态的方式):
a.利用多态进行动态类型识别:c++中的多态根据实际的对象类型调用对应的虚函数,可以在基类中定义虚函数返回具体的类型信息,所有的派生类都必须实现类型相关的虚函数,每个类中的类型虚函数都需要不同的实现。 示例代码:#includeusing namespace std; class parent { public: /*如果想在类中定义一个常量并且完成对常量的赋值 第一种,static const int ID = 0;使用静态常量 第二种,const int ID; 然后通过构造函数的初始化列表赋值 使用const常量 第三种,enum{ ID = 0 }; 使用枚举常量 注意:静态变量其实是种特殊的全局变量 静态常量其实就是特殊的全局常量 静态变量要在类外面进行初始化,静态常量由于是常量要在定义处初始化,所以不在外面初始化 */ enum{ ID = 0 }; virtual int type() { return ID; } }; class child : public parent { public: en