1,为什么会提出类型识别概念呢?
1,为什么在 C 语言中没有提出这个概念呢,就是因为在 C++ 中引入了面向对象的特性,面向对象里面有一个非常重要的原则就是赋值兼容性原则;
2,在面向对象中可能出现下面的情况:
1,基类指针指向子类对象;
2,基类引用成为子类对象的别名;
3,示意图:
1,p 指针字面意思是用来指向父类对象,而 p 又指向了子类对象;
2,当得到 p 指针后,我们是否有能力判断当前指针指向的是父类对象还是子类对象吗?目前没有办法通过一个父类指针来判断它指向的究竟是父类对象还是一个子类对象;
3,上图中展示的指针 p “静态类型”是 Base*,“静态类型”是指针它期望的类型,赋值兼容性使得 p 有可能指向的不是它期望的类型,而是子类类型,这时指针所指向的类型就叫做“动态类型”;
4,引用 r 静态类型是 Base&,r 的本意是引用父类的别名,但由于赋值兼容性,它也可以引用子类的别名,无法确定它的别名究竟是父类别名还是子类别名;
3,类型识别:
1,静态类型:
1,变量(对象)自身的类型;
1,写代码时就可以完全确定;
2,动态类型:
1,指针(引用)所指向对象的实际类型;
1,写代码时确定不了;
1,b 在代码运行时不一定指向父类对象,它有可能指向一个子类对象,因此 b 指针指向的是动态类型;
2,当 b 指针指向的是子类对象,则程序正常运行,将父类类型转换为子类类型是非常危险的,有可能产生 Bug;
(3),基类指针是否可以强制类型转换为子类指针取决于动态类型;
1,这样的转换和静态类型转换没有丝毫关系;
3,C++ 中如何得到动态类型?
4,动态类型识别:
1,解决方案(老师的思路):利用多态
1,在基类中定义虚函数返回具体的类型信息;
2,所有的派生类都必须实现类型相关的虚函数;
3,每个类中的类型虚函数都需要不同的实现;
1,调用类型虚函数就可以知道当前的对象究竟是什么类型,这样就可 以得到动态类型,达到动态类型识别效果;
5,动态类型识别编程实验:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Base 7 { 8 public: 9 virtual string type() 10 { 11 return "Base"; 12 } 13 }; 14 15 class Derived : public Base 16 { 17 public: 18 string type() 19 { 20 return "Derived"; 21 } 22 23 void printf() 24 { 25 cout << "I'm a Derived." << endl; 26 } 27 }; 28 29 class Child : public Base 30 { 31 public: 32 string type() 33 { 34 return "Child"; 35 } 36 }; 37 38 void test(Base* b) 39 { 40 /* 危险的转换方式 */ 41 // Derived* d = static_cast<Derived*>(b); 42 43 if( b->type() == "Derived" ) 44 { 45 Derived* d = static_cast<Derived*>(b); // 转换 46 47 d->printf(); // 使用指针 d,这里只是说明问题; 48 } 49 50 // cout << dynamic_cast<Derived*>(b) << endl; // 不够用,舍弃; 51 } 52 53 int main(int argc, char *argv[]) 54 { 55 Base b; 56 Derived d; 57 Child c; 58 59 test(&b); // 用 dynamic_cast 时,父类转换子类不成功,返回 0; 60 test(&d); 61 test(&c); // 用 dynamic_cast 时,子类间转换不成功,返回 0; 62 63 return 0; 64 }
1,最正规的转换用法应该是 dynamic_cast,可以判断 dynamic_cast 返回值来判断指针转换是否成功;
2,这里我们需要知道动态的类型究竟是什么,所以 dynamic_cast 在这里根本不够用,仅仅只能告诉我们转换是否成功;
3,这里通过虚函数返回类型名的方式就可以成功的得到动态类型名;
4,但是这里有个问题是长期维护,只要我们写一个新的类出来,必须都要实现这个虚函数,如果没有实现这个虚函数,后果将会造成对象的动态类型和实 &nbs