C++的四种类型转换的练习代码,该说的都在注释中,培养大家看代码的耐心~~
代码:
1 #include <iostream> 2 #include <stdlib.h> 3 4 /** 5 * @author:zanzan101 6 */ 7 8 using namespace std; 9 10 class A 11 { 12 private: 13 int data; 14 15 // 小知识:引用可以出现在类中,它的初始化和const类型类似,都是必须放到初始化列表中 16 int& ref; 17 public: 18 19 // 小知识:初始化列表中初始化的顺序,根据类中变量定义的顺序而定,与参数列表中的顺序无关 20 A():data(1), ref(data){} 21 int doSomething(){ 22 cout<< "A do something ..." <<endl; 23 return 123; 24 } 25 void toString() 26 { 27 cout<< "A" <<endl; 28 } 29 }; 30 class B : public A 31 { 32 public: 33 // 当仅仅返回值类型不同时 34 // 视为无多态行为的重写 35 // 和下面的toString函数类似 36 void doSomething(){ 37 cout<< "B do something ..." <<endl; 38 } 39 // 非虚函数的重写合法,但是无法触发多态行为 40 // 触发多态行为的唯一途径是父类的指针或者引用调用子类实现的虚函数 41 void toString() 42 { 43 cout<< "B" <<endl; 44 } 45 }; 46 47 class C 48 { 49 private: 50 int data; 51 public: 52 virtual void doSomething(){ 53 cout<< "C do something ..." <<endl; 54 } 55 }; 56 class D : public C 57 { 58 public: 59 // 错误演示: 60 // error C2555: “D::doSomething”: 重写虚函数返回类型有差异,且不是来自“C::doSomething”的协变 61 // virtual int doSomething(){ 62 // cout<< "B do something ..." <<endl; 63 // } 64 65 // 正确方法: 66 virtual void doSomething(){ 67 cout<< "D do something ..." <<endl; 68 } 69 }; 70 71 void func_void() 72 { 73 cout<< "func_void" << endl; 74 return; 75 } 76 77 int func_int() 78 { 79 cout<< "func_int" << endl; 80 return 1; 81 } 82 83 void do_func(void(*ptr_func)()) 84 { 85 ptr_func(); 86 } 87 88 int main() 89 { 90 // static_cast 如同普通转型一样 91 92 // const_cast 去掉常量性 93 94 // dynamic_cast 向下转换指针类型,前提是该指针或引用必须确实是指向的子类对象,否则返回NULL, 95 // 即最终结果不能出现子类指针指向父类对象的情况 96 97 // reinterpret_cast 转换函数指针 98 99 int num = 0; 100 char ch = 'A'; 101 num = static_cast<int>(ch); 102 cout<<"num = " << num << endl; 103 104 const int c_num = 1; 105 106 // 错误演示: 107 // c_num = 2; 108 109 // 错误演示: 110 // const_cast 只能处理指针或者引用 111 // int nc_num = const_cast<int>(c_num); 112 113 const int * p = &c_num; 114 int* q = const_cast<int*>(p); 115 *q = 2; 116 // 如果这个对象处于常量区,即使做了转型,也是无法修改 117 cout<<"c_num = " << c_num << endl; 118 119 p = # 120 121 // 错误演示: 122 // 对const类型指针所指对象赋值 123 // *p = 2; 124 125 // 正确方法: 126 q = const_cast<int*>(p); 127 *q = 2; 128 // 如果这个对象不处于常量区,则转型之后可以修改 129 cout<<"num = " << num << endl; 130 131 A a; 132 B b; 133 a.doSomething(); 134 135 // 错误演示 136 //int res = b.doSomething(); 137 // 看看有返回值对重载的影响 138 //cout<< "res = " << res << endl; 139 140 // 错误演示: 141 // error C2440: “初始化”: 无法从“A *”转换为“B *” 142 // B* ptr = &a; 143 144 // 正确方法: 145 // 向上转型,天生就可以转,但是向下转型必须用dynamic_cast 146 A* ptr1 = &b; 147 ptr1->doSomething(); 148 149 // 错误演示: 150 // error C2440: “初始化”: 无法从“A *”转换为“B *” 151 // 这里很有意思的是:ptr1明明指向的是B的对象,却不能赋值给ptr2,因此,dynamic_cast就有了用武之地 152 // B* ptr2 = ptr1; 153 154 // 错误演示: 155 // error C2683: “dynamic_cast”:“A”不是多态类型 156 // 用了dynamic_cast,却依然出错,因为A类没有虚函数,即:没有多态行为 157 // B* ptr2 = dynamic_cast<B*>(ptr1); 158 159 C c; 160 D d; 161 c.doSomething(); 162 d.doSomething(); 163 C* ptr3 = &d; 164 D* ptr4 = dynamic_cast<D*>(ptr3); 165 ptr3->doSomething(); 166 ptr4->doSomething(); 167 168 // 错误演示: 169 // 违背“该指针或引用必须确实是指向的子类对象”的前提 170 D* ptr5 = dynamic_cast<D*>(&c); 171 if(!ptr5) 172 cout<< "ptr5 is NULL...dynamic_cast failed!" << endl; 173 174 // 正常调用 175 do_func(func_void); 176 177 // 错误调用 178 // error C2664: “do_func”: 不能将参数 1 从“int (__cdecl *)(void)”转换为“void (__cdecl *)(void)” 179 // do_func(func_int); 180 181 // 正确方法: 182 // 使用reinterpret_cast 183 do_func(reinterpret_cast<void(*)()>(func_int)); 184 185 system("pause"); 186 187 return 0; 188 }
输出结果:
num = 65 c_num = 1 num = 2 A do something ... A do something ... C do something ... D do something ... D do something ... D do something ... ptr5 is NULL...dynamic_cast failed! func_void func_int 请按任意键继续. . .