整站优化关键词推广,品牌vi形象设计公司,做网站要学c语言,wordpress 统计代码添加前 言
C 既支持 C 风格的类型转换#xff0c;又有自己风格的类型转换。C 风格的转换格式很简单#xff0c;但是有不少缺点#xff1a;
转换太过随意#xff0c;可以在任意类型之间转换。你可以把一个指向 const 对象的指针转换成指向非 const 对象的指针#xff0c;把一…前 言
C 既支持 C 风格的类型转换又有自己风格的类型转换。C 风格的转换格式很简单但是有不少缺点
转换太过随意可以在任意类型之间转换。你可以把一个指向 const 对象的指针转换成指向非 const 对象的指针把一个指向基类对象的指针转换成一个派生类对象的指针这些转换之间的差距是非常 巨大的但是传统的C语言风格的类型转换没有区分这些。C 风格的转换没有统一的关键字和标示符。对于大型系统做代码排查时容易遗漏和忽略。
C 风格完美的解决了上面两个问题。
对类型转换做了细分提供了四种不同类型转换以支持不同需求的转换类型转换有了统一的标示符利于代码排查和检视。
下面分别来介绍这四种转换static_cast、dynamic_cast、const_cast、reinterpert_cast它们都是类模板。
一、static_case(静态转换)
1使用场景
在基本数据类型之间转换如把 int 转换为 char这种带来安全性问题由程序员来保证在有类型指针与 void * 之间转换用于类层次结构中基类和派生类之间指针或引用的转换。 上行转换派生类----基类是安全的 下行转换基类----派生类由于没有动态类型检查所以是不安全的。 2使用特点主要执行非多态的转换操作用于代替C中通常的转换操作。隐式转换都建议使用 static_cast 进行标明和替换。不能使用 static_cast 在有类型指针内转换。 3示例程序如下所示
#include iostreamusing namespace std;class CBase // 基类(父类)
{};class CDerived : public CBase // 派生类(子类)
{};int main()
{// 1. 使用static_cast在基本数据类型之间转换float fval 10.12;int ival static_castint(fval); // float -- intcout ival endl; // out: 10// 2. 使用static_cast在有类型指针与void *之间转换int *intp ival;void *voidp static_castvoid *(intp); // int* -- void*// cout *voidp endl; // error,voidp的大小未知long *longp static_castlong *(voidp);cout *longp endl; // out: 10// 3. 用于类层次结构中基类和派生类之间指针或引用的转换// 上行转换派生类----基类是安全的CDerived *tCDerived1 nullptr;CBase *tCBase1 static_castCBase*(tCDerived1);// 下行转换基类---- 派生类由于没有动态类型检查所以是不安全的CBase *tCBase2 nullptr;CDerived *tCDerived2 static_castCDerived*(tCBase2); //不会报错但是不安全// 不能使用static_cast在有类型指针内转换float *floatp fval; //10.12的addr//int *intp1 static_castint *(floatp); // error,不能使用static_cast在有类型指针内转换cout *floatp endl; // out: 10.12
}/*
输出结果10
10
10.12
*/
二、dynamic_cast(动态转换)
1使用场景
用于将一个父类的指针/引用转化为子类的指针/引用下行转换。 2使用特点基类必须要有虚函数因为 dynamic_cast 是运行时类型检查需要运行时类型信息而这个信息是存储在类的虚函数表中。对于下行转换dynamic_cast 是安全的当类型不一致时转换过来的是空指针而 static_cast 是不安全的。对指针进行 dynamic_cast失败返回 NULL成功返回正常 cast 后的对象指针对引用进行 dynamic_cast失败抛出一个异常成功返回正常 cast 后的对象引用。 3示例程序如下所示
#include iostreamusing namespace std;class CBase // 基类(父类)
{
public:// dynamic_cast在将父类cast到子类时父类必须要有虚函数virtual int test() { return 0; } // 一定要是 virtual
};class CDerived : public CBase // 派生类(子类)
{
public:int test() { return 1; }
};int main()
{CBase *p_CBase new CBase; // 基类对象指针CDerived *p_CDerived dynamic_castCDerived *(p_CBase); // 将基类对象指针类型转换为派生类对象指针CBase i_CBase; // 创建基类对象CBase r_CBase i_CBase; // 基类对象的引用CDerived r_CDerived dynamic_castCDerived (r_CBase); // 将基类对象的引用转换派生类对象的引用
}
三、const_cast(常量转换)
1使用场景
常量指针或引用与非常量指针或引用之间的转换。 2使用特点cosnt_cast 是四种类型转换符中唯一可以对常量进行操作的转换符。去除常量性是一个危险的动作尽量避免使用。 3示例程序如下所示
#include iostreamusing namespace std;int main()
{int value 100;const int *cpi value; // 定义一个常量指针//*cpi 200; // 不能通过常量指针修改值// 1. 将常量指针转换为非常量指针,然后可以修改常量指针指向变量的值int *pi const_castint *(cpi);*pi 200;// 2. 将非常量指针转换为常量指针const int *cpi2 const_castconst int *(pi); // *cpi2 300; //已经是常量指针const int value1 500;const int c_value1 value1; // 定义一个常量引用// 3. 将常量引用转换为非常量引用int r_value1 const_castint (c_value1);// 4. 将非常量引用转换为常量引用const int c_value2 const_castconst int (r_value1);
}
四、reinterpret_cast(不相关类型的转换)
reinterpret 的英文含义有重新转换的含义就相当于 C 语言中不相关类型的转换,强转。 1使用场景
用在任意指针或引用类型之间的转换。能够将整型转换为指针也可以把指针转换为整型或数组。 2使用特点reinterpret_cast 是从底层对数据进行重新解释依赖具体的平台可移植性差。不到万不得已不用使用这个转换符高危操作。 3示例程序如下所示
#include iostreamusing namespace std;int main()
{int value 100;// 1. 用在任意指针或引用类型之间的转换double *pd reinterpret_castdouble *(value);cout *pd *pd endl;// 2. reinterpret_cast能够将指针值转化为整形值int *pv value;int pvaddr reinterpret_castint(pv);cout pvaddr hex pvaddr endl;cout pv pv endl;
}/*
输出结果*pd -9.25596e61
pvaddr 8ffe60
pv 008FFE60
*/
五、扩展
下面程序中参数 pb 指向的是 B 类对象pd1 的值不为0而 pd2 的值为 0。
#include iostreamusing namespace std;class B
{int m_iNum;virtual void foo() {};
};
class D:public B
{char *m_szName[100];
};void func(B* pb)
{D *pd1 static_castD *(pb);D *pd2 dynamic_castD *(pb);cout pd1 endl; //00CFF7C0cout pd2 endl; //00000000
}int main()
{B pb; //父类对象pbcout pb: pb endl; //pb: 00CFF7C0 func(pb);return 0;
}/*
输出结果pb: 00CFF7C0
00CFF7C0
00000000
*/