首页
登录 | 注册

【C++语言99个常见编程错误】第4章 类型转换问题

4章 类型转换问题

void*为类型转换的中介

在强制类型转换中,转换到void*类型的结果会将带类型的指针的类型信息全部抹除

使用static_cast进行相对安全和可抑制的类型转换,不安全的、平台相关的,采用reinterpret_cast

C++标准只保证以void*为中介类型的转换前后使用同一类型,才能获取正确的结果

截断问题

将一个派生类对象复制到一个基类对象时,派生类专属的数据和行为会被抹除

这个问题常发生在传递引用或指针的参数时

目标类型为指向常量的指针的类型转换

我们可以把指向非常量的指针复制给一个指向常量的指针

我们可以修改指向常量的指针所涉的数据,只要这些数据实际上并非是常量,或者它们确实是常量,但是却被没被分配到只读区域

指向const常量的指针只是看起来是指向const常量的指针

以指涉物为指向常量的指针类型的类型为目标类型的类型转换

char **ppc;

const char **ppcc = ppc;// 错误!

使用引用类型或者标准库组件以避免一如多级指针,这是较好的选择

指向多位数组的指针带来的问题

sizeof对数组名求值,得到的数组的尺寸,对常量指针得到的是指针本身的尺寸

数组有地址的,通过数组名来指明的,但数组名本身没有地址

多维数组的首地址的类型是个数组,而不是其基本类型

未经检验的向下转型

编译器所玩的偏移量算术的把戏会先入为主地认为基类的地址从属于派生类对象的基类类型子对象地址

安全的向下转型使用dynamic_cast

类型转换运算符的误用

使用显式类型转换函数进行类型转发分派,将仅有一个参数的构造函数打上explicit标志

使用构造函数转换用户自定义类型,而使用类型转换符来转换内建类型

没有任何直接的手法命令编译器去调用构造函数或对其取址

始料未及的构造函数类型转换

隐式进行的构造函数类型转换常常会导致难以理解的代码,还会引入晦涩的代码缺陷

将一个构造函数声明为explicit同样可以影响到它的合法初始化语句集

直接初始化优于复制初始化

class String

{

    public:

        explicit String (const char*);

        operator const char*() const;

};

String name1("Fred"); //没问题

name1 = "Joe";  //错误,隐式类型转换,从const char*String

const char &cname = name1; //逆向隐式类型转换,没问题

String name2 = cname; //错误,隐式类型转换,从const char*String

String name3 = String(cname); //显式类型转换,没问题

多继承条件下进行强制类型转换

每个完整的class对象的基类子对象都有一个与众不同的地址,而这些地址的每一个都是该完整对象的合法地址。

最好还是避免对class对象做静态强制类型转换

对非完整类型做强制类型转换

仅声明的class类型没有定义,但仍然可以声明指向此类类型的指针和引用,并可以声明以该类型为参数及返回值的类型的函数

如果要对仅声明的类型做强制转换,必须用到reinterpret_cast

旧式强制类型转换

尽量不要使用旧式强制类型转换,任何将常量性抹除的强制类型转换都有潜在的危险性和不可移植性

静态强制类型转换

静态强制类型转换包括了static_castreinterpret_castconst_cast以及旧式强制类型转换

采用静态强制类型转换就是要告诉编译器:别废话,按我说的来!

形参引发临时对象生成的初始化

以传递引用的方式来传递参数开销小,而且固定,不随着(模版实例化)参数类型的改变而改变

STL中,仍是采用传值的方式,调用过程生成匿名对象

临时对象的生存期

临时对象的生存期从其被创建的时间点开始,到最大可能的闭合表达式结束处终止

使用相对复杂些(却不引起生存期问题)的表达式,或声明一个具名的临时对象以扩展String对象的生存周期

引用和临时对象

引用必须使用左值来初始化

const int &p = 12;特定情况下,也可以从一个非左值出发来创建一个左值,该临时对象与以它为初始化物的引用共存亡

不要返回指向常量的引用的形式参数,另一种备选方案就是把形式参数之引用的指涉物改为非常量,这样一旦要求在初始化时生成临时对象,就会引发一个编译时错误

dynamic_cast带来的多义性解析失败

多重继承下,以非虚方式继承,会有多个基类。这就有可能带来了dynamic_cast的二义性

dynamic_cast不一定是动态的,因为它不一定就会做运行期校验

对逆变性的误解

逆变性:指向成员的指针的隐式类型转换路径和指向class对象的指针的隐式类型转换路径恰好相反

 



2020 jeepxie.net webmaster#jeepxie.net
10 q. 0.009 s.
京ICP备10005923号