C++类型转换

目录


知识点:

  • 任何一个转型动作往往令编译器编译出运行期间执行代码
  • 显示转型可能发生拷贝
  • 显示转换会不会抛出异常

转换符:

  • static_cast:强迫隐式转换,不包含底层const的任何具有明确定义的类型转换。——底层const也可以转,比如boost::simple_segregated_storage中的 nextof
    + 适用场合:编译器隐式执行的任何类型转换都可以由static_cast来完成
     a. 需要把一个较大的算术类型赋值给较小的类型
     b. 对于编译器无法自动执行的类型转换如:子类(指针)转成基类(指针)但不做运行时的检查,不如dynamic_cast安全。static_cast仅靠类型转换语句中提供的信息来进行转换,而dynamic_cast则会遍历整个类继承体系进行类型检查,因此dynamic_cast在执行效率要差一些。
     c. void* 转成具体结构,不同指针类型之间的转换使用static_cast作为桥梁
     d. int转成对应的枚举
     e. 将non-const转成const等,但不能将const转成non-const——不需要吧,non-const可以直接给const
     f. 针对右值引用的特许转换规则:虽然不能隐式的将一个左值转换为右值引用,但可以用static_cast显式地将一个左值转换为一个右值引用,也就是std::move的功能吧:static_cast(t)
  • const_cast:只能改变底层const;因为不能把一个const对象赋给非const对象,通过该函数可进行转换:去const属性;
    + 适用场合:——待验证
     a. const_cast常常用于有函数重载的上下文中
     b. 去const属性
const char * pc;
char * p = const_cast<char*>(pc);     //正确但通过p写值是未定义的行为
  • reinterpret_cast:通常为运算对象的位模式提供较低层次上的重新解释,执行低级转型,实际动作取决于编译器,这也表示他是不可移植的,转换结构几乎都是在执行期定义。
    • 要点:一个指向字符串的指针是如何地与一个指向整数的指针或者一个指向其他自定义类型对象的指针有所不同呢?从内存需求的观点来说并没有不同,它们三个都需要足够的内存来放置一个机器地址。指向不同类型各指针之间的差异,既不在其指针表示法不同,也不在其内容不同,而是其所寻址出来的对象类型不同,也就是说,指针类型会教导编译器如何解释某个特定地址中的内存内容及其大小
    • 适用场合:从语法上看,这个操作符仅用于指针类型的转换(返回值是指针)。它用来将一个类型指针转换为另一个类型指针,它只需在编译时重新解释指针的类型。这个操作符基本不考虑转换类型之间是否是相关的。
    • 注意:在gcc上大转小不被允许,需要加编译参数:-fpermissive
    • 代码示例:
int num = 0x00636261;//用16进制表示32位int,0x61是字符'a'的ASCII码
int * pnum = &num;
char * pstr = reinterpret_cast<char *>(pnum);
cout << "pnum指针的值: " << pnum << endl;
cout << "pstr指针的值: " << static_cast<void *>(pstr) << endl;//直接输出pstr会输出其指向的字符串,这里的类型转换是为了保证输出pstr的值
// 以上两行输出的地址值是一样的
cout << "pnum指向的内容: " << hex << *pnum << endl;  // 输出636261
cout << "pstr指向的内容: " << pstr << endl;          // 输出 abc
// 如果将num的值改为64636261,patr输出abcd***(abcd后几个乱码),原因是,pstr会一直输出直到遇到'\0'
// 所以,如果访问到非法地址,会崩溃
  • dynamic_cast:支持运行时类型识别,主要被用于安全地沿着类的继承关系向下进行类型转换,将一个基类转换成派生类

    • 语法:A=dynamic_cast(B) (typeA通常含有虚函数)
    • 该运算符把B转换成typeA类型的对象。TypeA必须是类的指针、类的引用或者void *——只能针对指针或引用进行强转;
    • dynamic_cast的转换是在运行时进行的(指向派生类的基类指针可以转成派生类类型,但静态的基类转派生类是不会成功的,同样适用于引用),它的一个好处是会在运行是做类型检查,如果对象的类型不是期望的类型,它会在指针转换的时候返回NULL,在引用转换的时候抛出一个std::bad_cast异常。所以有两个步骤:
      • 第一,判断是不是某个类型;
      • 第二,是的话就把指针强转成要的类型,不是就返回NULL或抛出异常;
    • dynamic_cast一般只在继承类对象的指针之间或引用之间进行类型转换。如果没有继承关系,则被转化的类具有虚函数对象的指针进行转换,不能被用于缺乏虚函数的类型上(more effective c++ 2)——待验证?
  • 备注:

    • 尽量避免类型转换,特别是dynamic_cast,有两种方法代替:
      • 使用容器并直接在其中存储指向derived class的指针
      • 使用虚函数代替
  • 保证安全的向下转型操作:

    • 需要额外的空间以储存类型信息,通常是一个指针,指向某个类型信息节点
    • 需要额外的时间以决定执行期的类型
  • 保证安全的动态转型:dyanmic_cast可以在执行期决定真正的类型,如果是安全的(也就是说父类指针指向派生类对象),这个运算符会传回被适当转型过的指针,如果不是安全的,会传回空

    • 究竟用static还是dynamic,必须视pt指向的是否是一个多态对象而定
    • 引用不是指针,如果dynamic_cast运算符施行于一个引用时,不能够提供于针对于指针的那一组true/false,因为如将一个引用设为0,会引起一个临时对象被产生出来,该临时对象的初值为0。取而代之的是:
      • 如果引用真正参考到适当的派生类,向下转换会继续执行
      • 如果引用不是某一种派生类,由于不能够传回0,丢出一个bad_cast的异常
  • 指针类型转换:
    C++类型转换_第1张图片

你可能感兴趣的:(C++编程,c++,开发语言)