C++强制类型转换

1、概述

传统运转换延续了C的形式,但是只能在数值类型上使用,对于其他类型(引用和指针),标准c++的有以下四种强制类型转换方式:

const_cast,reinterpret_cast,static_cast,dynamic_cast

2、const_cast

用法: const_cast <new_type> (expression)

const_cast转换符是用来移除或添加变量的const, volatile, 和 __unaligned限定符,而不能用于类型转换。

2.1 移除const

移除const操作。

const int constant = 12;
const int* p = &constant;
int* modifier = const_cast<int*>(p);
*modifier = 123;
cout<<*modifier<<endl;

2.2 添加const

int data = 13;
int *pdata = &data;
const int *result = const_cast<const int*>(pdata);

其他限定符,如volatile等与上面的类似。

3 static_cast

用法:static_cast <new_type> (expression)

该运算符把expression转换为new_type类型,但没有运行时类型检查来保证转换的安全性。

使用场景:

1 用于类层次结构中基类和子类之间指针或引用的转换。
    进行上行转换(把子类的指针或引用转换成基类表示)是安全的;
    进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。

2 用于基本数据类型之间的转换
    如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。

3 把空指针转换成目标类型的空指针。

4 把任何类型的表达式转换成void类型。

使用实例:

class Data
{
public:
    int data = 10;
    virtual void get();
};

class SubData: public Data
{

};
SubData *sd = new SubData;
Data *d = static_cast<Data*>(sd);

SubData *sd2 = static_cast<SubData*>(d);

注意:
static_cast不能去掉expression的const、volitale、或者__unaligned属性

4 dynamic_cast

用法:dynamic_cast <new_type> (expression)

该运算符把expression转换成new_type类型的对象。参数说明:

new_type必须是类的指针、类的引用或者void *;
    如果new_type是类指针类型,那么expression也必须是一个指针;
    如果new_type是一个引用,那么expression也必须是一个引用。

使用场景:

1 只能在继承类对象的指针之间或引用之间进行类型转换
    上行转换,同static_cast;
    下行转换,dynamic_cast具有类型检查的功能,比static_cast更安全。
2 这种转换并非在编译时,而是在运行时,动态的  
3 没有继承关系,但被转换的类具有虚函数对象的指针进行转换 

注:只有对象具有多态属性的时候,才可以对齐进行dynamic_cast。

使用示例:

class NoExtend
{
    virtual void set();
};

class NoExtend2
{
};
SubData *sd = new SubData;
Data *d = dynamic_cast<Data*>(sd);

Data &d2 = *d;
SubData &sd2 = dynamic_cast<SubData&>(d2);

NoExtend *ne = new NoExtend;
Data *d3 = dynamic_cast<Data*>(ne);
NoExtend2 *sd3 = dynamic_cast<NoExtend2*>(ne);

5、reinterpret_cast

用法: reinterpret_cast <new_type> (expression)

reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。也即将一个类型指针转换为另一个类型指针,这种在转换不修改指针变量值数据存放格式。reinterpret_cast不能用于非指针的转换

使用场景:
reinterpret_cast用在任意指针(或引用)类型之间的转换,一般情况有以下这些常用场景:

从指针类型到一个足够大的整数类型
从整数类型或者枚举类型到指针类型
从一个指向函数的指针到另一个不同类型的指向函数的指针
从一个指向对象的指针到另一个不同类型的指向对象的指针
从一个指向类函数成员的指针到另一个指向不同类型的函数成员的指针
从一个指向类数据成员的指针到另一个指向不同类型的数据成员的指针

使用示例:

double d=12.34;
double* p = &d;
long* pi = reinterpret_cast<long *> (p);
class C1{};
class C2{};
C1* pc1 = new C1;
C2* pc2=reinterpret_cast<C2*>(pc1);
double* doub=reinterpret_cast<double*> (pc2);

6、interface_cast

interface_cast是android中定义的类型转换,其源码位于frameworks/native/include/binder/Iinterface.h以下针对IServiceManager分析

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

其中INTERFACE为传入进来的IServiceManager,在IServiceManager中关于asInterface的实现部分,只有这一段IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");,它实际调用的还是Iinterface中的宏定义。

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const android::String16 I##INTERFACE::descriptor(NAME);             \
    const android::String16&                                            \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
            const android::sp<android::IBinder>& obj)                   \
    {                                                                   \
        android::sp<I##INTERFACE> intr;                                 \
        if (obj != NULL) {                                                  \
            //根据name描述符,也就是"android.os.IServiceManager"通过方法      \
            //queryLocalInterface查询本地是否有此Interface                  \
            //没有就创建一个新的,其实是new BpServiceManager。                \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \

BpServiceManager的实现也位于ISeviceManager.cpp中。

BpServiceManager(const sp<IBinder>& impl)
    : BpInterface<IServiceManager>(impl)
{
}

最终发现,其最初就是一个IServiceManager,先转成IBinder,再后面转回来而已。

### C++ 强制类型转换方法及其使用指南 #### 新式转型概述 在C++中,强制类型转换被称为新式转型,区别于C语言中的旧式转型。新式转型提供了四种不同的关键字来执行特定类型的转换操作:`static_cast`、`dynamic_cast`、`const_cast` 和 `reinterpret_cast`[^1]。 #### Static Cast (静态转换) `static_cast` 是一种编译期检查的类型转换机制,适用于基本数据类型间的相互转换以及具有继承关系的对象之间安全的方向上的转换。例如: ```cpp double dValue = 3.14; int iValue = static_cast<int>(dValue); ``` 对于指针或引用来说,当基类和派生类存在单根继承体系时可以实现向下转型(即从基类到派生类),但是这种情况下应该优先考虑使用更安全的方式——`dynamic_cast`。 #### Dynamic Cast (动态转换) `dynamic_cast` 主要用于处理多态对象之间的转换,在运行期间能够判断两个类型间是否存在合法的关系并返回相应结果。如果尝试非法的操作,则会抛出异常或者返回null指针取决于具体场景。这使得它成为最安全但也可能是性能开销最大的选项之一: ```cpp Base* basePtr = new Derived(); Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); if(derivedPtr != nullptr){ // 成功转换... } else{ // 转换失败... } ``` 此功能特别适合用来验证是否可以从某个已知接口获取更加具体的实例化版本[^3]。 #### Const Cast (常量属性修改) `const_cast` 的作用在于移除变量声明时所附加的 const 或 volatile 属性。虽然有时确实有必要这样做,但在大多数时候应当尽量避免改变原本设计意图下的不可变性约束,因为这可能会引发未定义行为的风险。 ```cpp void someFunction(const int& value){ int* nonConstValue = const_cast<int*>(&value); (*nonConstValue)++; } // 注意上述做法并不推荐除非有充分理由证明其安全性。 ``` #### Reinterpret Cast (重新解释位模式) 最后是 `reinterpret_cast`, 它允许程序员直接操纵底层二进制表示形式来进行几乎任何种类的数据视图变换。然而由于缺乏语义层面的理解和支持,误用该特性极易造成难以调试的问题甚至危及整个系统的稳定性。因此仅限于那些真正需要低级控制的应用场合下谨慎采用,并且通常只会在非常特殊的情况下才会涉及到此类操作[^2][^4]: ```cpp uintptr_t rawAddress = reinterpret_cast<uintptr_t>(&someObject); void* genericPointer = reinterpret_cast<void*>(rawAddress); ``` 综上所述,每种类型转换都有各自适用范围内的最佳实践指导原则,合理选择合适的工具可以帮助开发者写出既高效又可靠的代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值