【C++】类型转换

  • 引言

  C++风格的四种类型转换方法:static_cast、dynamic_cast、reinterpret_cast、const_cast。

  欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

  • static_cast

  使用 static_cast 可以进行接近C风格的静态转换,但增加了安全性考虑。

double d = 3.14;
int i = static_cast<int> (d);

  欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

  • dynamic_cast

  上行转换(子类指针转父类指针)一般是安全的,当然必须得 public 继承才合法。下行转换(父类指针转子类指针)很可能不安全(例如当指针指向父类对象时)。

  可以采用 dynamic_cast<type> (expression) 动态转换的条件是:type为指针或引用,下行转换时基类为多态(有虚函数,从而可以在虚表中放一个类型信息指针—— dynamic_cast 的一种典型实现)。对于不安全的指针下行转换,dynamic_cast 返回 NULL。

class Dad {};
class Son: public Dad
{
public:
    void func ();
};

int main ()
{
    Dad d;
    Son *s1 = (Son*) &d;  // 编译通过
    s1->func ();  // 运行出错
    Son *s2 = static_cast<Son*> (&d);  // 编译报错: 无法转换
    s2->func ();
    Son *s3 = dynamic_cast<Son*> (&d);  // 编译报错: Dad不是多态类型, 除非Dad中有虚函数
}
class Dad
{
    virtual void func ();
};
class Son: public Dad {};

int main ()
{
    Son son;
    Dad *pd = dynamic_cast<Dad*> (&son);  // 上行转换, ok
    Dad dad;
    Son *ps = dynamic_cast<Son*> (&dad);  // 下行转换, ps=0

    Dad *pdad = new Dad, *pson = new Son;
    ps = dynamic_cast<Son*> (pdad);  // 下行转换, ps=0
    ps = dynamic_cast<Son*> (pson);  // 下行转换, ok
}

  如上面这个例子所示,对指针下行转换时,如果失败 dynamic_cast 会返回0;而对引用下行转换时,如果失败会抛出 bad_cast 异常。

void f (Dad &dad)
{
    try {
        Son &son = dynamic_cast<Son&> (dad);
    }
    catch ( bad_cast ) {
        // 异常处理
    }
}

  当转换源指针或目标指针为 void * 时,dynamic_cast 总认为安全。目标指针为 void * 可以用于确定多态类型的对象的起始地址。

class A
{
    virtual void func ();
};

int main ()
{
    A *a = new A;
    void *v = dynamic_cast<void*> (a);  // 同样要求A多态
    a = dynamic_cast<A*> (v);
}

  和 typeid 一样,dynamic_cast 使用了“运行时类型信息” RTTI(Run Time Type Information),某些平台可能不支持。

  欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

  • reinterpret_cast

  使用 reinterpret_cast<type> (expression) 可以在指针之间或指针与整数之间转换类型,同样要求 type 为指针或引用。

int *p = new int;
long i = reinterpret_cast<long> (p);
p = 0;  // p 不再指向 new int
p = reinterpret_cast<int*> i;  // p 重新指向 new int

  欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

  • const_cast

  使用 const_cast 可以将常量转换为变量,去除 const 属性。

const char *str = "hello";
char *s = const_cast<char*> (str);

  在类 A 的 const 成员函数中,如果想要修改 A 的成员变量,可以先将 this 强制去除 const 属性。但当对象本身就是常量时,结果将不可预见。

class A
{
    bool m;
public:
    void func () const
    {
        A *a = const_cast<A*> (this);  // 强制去除const属性
        a->m = true;
    }
};

int main ()
{
    A a1;
    const A a2;
    a1.func ();  // ok
    a2.func ();  // 无定义行为
}

  因此,令某些成员变量可被 const 成员函数修改的更好的解决方案是,将成员变量声明为 mutable,或者将这些成员变量封装到结构体指针中。

  欢迎来到 lovickie 的博客 http://www.cnblogs.com/lovickie

  • 结语

  无。

时间: 2024-10-14 00:31:41

【C++】类型转换的相关文章

More Effective C++

条款一:指针与引用的区别 指针与引用看上去完全不同(指针用操作符'*'和'->',引用使用操作符'.'),但是它们似乎有相同的功能.指针与引用都是让你间接引用其他对象.你如何决定在什么时候使用指针,在什么时候使用引用呢? 首先,要认识到在任何情况下都不能用指向空值的引用.一个引用必须总是指向某些对象.因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量.相反,如果变量肯定指向一个对象,例如你的设计不允许变量为

Javascript类型转换的规则实例解析

http://www.jb51.net/article/79916.htm 类型转换可以分为隐式转换和显式转换,所谓隐式转换即程序在运行时进行的自动转换,显式转换则是人为的对类型进行强制转换.Javascript的变量是松散类型的,它可以存储Javascript支持的任何数据类型,其变量的类型可以在运行时被动态改变.请看示 例: ? 1 2 3 var n = 10; n = "hello CSSer!"; n = {}; 上面的示例中,首先声明n变量并初始化其值为10(整数类型),接

进制、类型转换、提升

进制 java支持四种进制表示 进制 示例 前缀 备注 十进制 int x = 10;     二进制 int x = 0b10; 0b或0B 计算机储存 八进制 int x = 010; 0 兼容以前程序 十六进制 int x = 0xceaf 0x或0X 0~9,a~f 细节: 一个十六进制位可以表示四个二进制位 当数值位数较多时,可以使用下划线对数字进行隔开,例:1_230_456 字面常量 整数:字面常量为int型,如果要表示long类型的字面常量,使用L或l做后缀,建议使用L,因为字母

第二节 变量 、 基本类型 、 运算符 、 表达式 、 数据 、 类型转换 、 常量

一:变量 定义:在程序运行中随时可以发生变化的量 变量声明:变量的声明只能以数字,字母,下划线,且字母不能开头,同时不能是C#中的关键字. 变量使用:变量必须先声明才能使用,变量赋值必须是对应类型,int age=true:这样就会报错. 二:常量 定义:在程序的生存期内不发生更改的不可变值 常量声明:const关键字  public const int age=10; age在程序内不会变,值一直是10: 三:内置数据类型(数值类型和非数值类型) 数值类型:分为整型和非整型 整型如下图: 非整

03 php 数据类型:整数,进制转换,浮点,字符,布尔,数组,空类型,类型转换,算术运算,比较运算

03 数据类型:整数,进制转换,浮点,字符,布尔,数组,空类型,类型转换, 算术运算,比较运算,逻辑运算,短路现象, 三目运算符,字符型运算: 数据类型 整体划分 标量类型: int, float, string, bool 复合类型: array,     object 特殊类型: null,     resouce 整数类型int, integer 3种整数表示法 十进制写法:123: $n1 = 123; 八进制写法: 0123 $n2 = 0123; 十六进制写法: 0x123 $n3

java 复习 - 数据类型转换

基本数据类型转换两天原则 低精度的值可以直接赋值给高精度的变量,直接变成了高精度 高精度的值不可以直接赋值给低精度的变量. 不同类型变量混合运算之后,得到的结果是精度最高的类型 基本数据类型和字符串之间的转换 基本数据类型转换成字符串 使用String 的valueOf()函数. 使用方法: String.valueOf(各种基本类型)  得到一个字符串.例子如下:  package typeConvertTest; public class TypeConvertTest{  public s

C++:类型转换

5.3 类型转换 5.3.1 系统预定义类型间的转换 1. 隐式转换: 例如: int x=5,y;             y=3.5+x; //系统会自动先将int型的5转换为double型的5.0,在和3.5进行加法运算. 隐式类型转换的主要规则: a.在赋值表达式A=B的情况下,赋值运算符右端B的值需要转换为A的类型后进行赋值. b.当char或short类型变量与int类型变量进行运算时,将char或short类型转换为int类型. c.当两个操作对象类型不一致时,在算术运算前,级别低

基本数据类型转换

自动类型转换:容量小的数据类型自动转换成容量大的数据类型.            char                           int long float double byte     short 一字节是8位,一字是2字节. 有多种类型的数据计算时.系统会将所有的数据类型转换成最大的数据然后进行计算. byte short char之间不会自动转换,他们三者计算会首先转换成int在进行计算. 当把任何基本类型的数据和自负类型的数据进行链接运算(+),得到的是字符类型的数据.

C++强制类型转换操作符 const_cast

const_cast也是一个强制类型转换操作符.<C++ Primer>中是这样描述它的: 1.将转换掉表达式的const性质. 2.只有使用const_cast才能将const性质性质转化掉.试图使用其他三种形式的强制转换都会导致编译时的错误.(添加const还可以用其他转换符,如static_const) 3.除了添加const或删除const特性,使用const_cast符来执行其他任何类型的转换都会引起编译错误.(volatile限定符也包括,不过我不怎么了解,本文主要说const)

Objective-C数据类型、数据类型转换

数据类型 1.Objective-C数据类型可以分为:基本数据类型.对象数据类型和id类型. 2.基本数据类型有:int.float.double和char类型. 3.对象类型就是类或协议所声明的指针类型,例如: NSAutoreleasePool *pool ,其中,NSAutoreleasePool是一个类,NSAutoreleasePool *是它指针类型或叫对象类型. 4.id类型可以表示任何类型,一般只是表示对象类型,不表示基本数据类型,所以刚才的变量可以声明pool也可以声明为id