C++强制类型转换对比测试

0、总结

1、static_cast(object)
相当于传统的C语言里的强制转换,能转换非指针类型类和变量
2、dynamic_cast(object)
只能转换具有父子关系的类指针,而且下行转换还不许包含多态(虚函数)
条件比较苛刻,执行效率不高
3、reinterpret_cast(object)
强制转换一切类型指针,无任何检查,正确性由程序员自己负责

1、普通类型转换测试

指针和整数之间转换、指针之间转换(void*除外)只能用reinterpret_cast
整数之间转换可以只能用static_cast

void testGeneralType(void) //普通类型转换
{
    int a = 0;
    char b = 2;
    int* p = nullptr;
    char* cp = nullptr;
    void* vp = nullptr;

    std::cout << "\n####1、普通类型转换测试####\n";

    //1、char -> int
    a = static_cast<int>(b);        //ok
    //a = dynamic_cast<int>(b);     //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    //a = reinterpret_cast<int>(b); //error,不能转换普通类型

    //2、int -> int*
    //p = static_cast<int*>(a);     //error,无效类型转换
    //p = dynamic_cast<int*>(a);    //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    p = reinterpret_cast<int*>(a);  //ok

    //3、int* -> int
    //a = static_cast<int>(p);     //error,无效类型转换
    //a = dynamic_cast<int>(p);    //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    a = reinterpret_cast<int>(p);  //ok

    //4、char* -> int*
    //p = static_cast<int*>(cp);    //error,无效类型转换
    //p = dynamic_cast<int*>(cp);   //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    p = reinterpret_cast<int*>(cp); //ok

    //5、void* -> int*
    p = static_cast<int*>(vp);      //ok
    //p = dynamic_cast<int*>(vp);   //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    p = reinterpret_cast<int*>(vp); //ok

    //6、int* -> void*
    vp = static_cast<void*>(p);      //ok
    //vp = dynamic_cast<void*>(p);   //error,操作数(object)必须是指向完整类类型的指针
    vp = reinterpret_cast<void*>(p); //ok
}

2、类转换测试

只能用static_cast,但无法进行下行转换

void testClass(void) //类转换
{
    A a;
    B b;
    Father f;
    Son s;

    std::cout << "\n####2、类的转换测试####\n";

    //1、上行转换
    std::cout << "上行转换:";
    f = static_cast<Father>(s);        //ok
    f.fun();
    //f = dynamic_cast<Father>(s);     //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    //f = reinterpret_cast<Father>(s); //error

    //2、下行转换
    //s = static_cast<Son>(f);      //error,不存在转换规则
    //s = dynamic_cast<Son>(f);     //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    //s = reinterpret_cast<Son>(f); //error,不允许

    //3、不相关类型转换
    std::cout << "不相关类转换:";
    a = static_cast<A>(a);        //ok
    a.fun();
    //a = dynamic_cast<A>(a);     //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    //a = reinterpret_cast<A>(a); //error,不允许
}

3、类的指针转换测试

reinterpret_cast可以任意转换
static_cast和dynamic_cast只能转换具有父子关系的类型指针
其中dynamic_cast进行下行转换时必须包含多态(虚函数)

void testClassPointer(void) //类的指针转换
{
    A* a = new A; //A和B是两个毫无关联的类
    B* b = new B;
    Father* f = new Father; //父类
    Son* s = new Son;       //子类

    std::cout << "\n####3、类的指针转换测试####\n";

    //1、上行指针转换
    std::cout << "上行转换:\n";
    Father* f1 = static_cast<Father*>(s);  //Son -> Father
    Father* f2 = dynamic_cast<Father*>(s);
    Father* f3 = reinterpret_cast<Father*>(s);
    f1->fun(); //都能通过
    f2->fun();
    f3->fun();

    //2、下行指针转换
    std::cout << "下行转换:\n";
    Son* s1 = static_cast<Son*>(f);      //可以不包含多态
    Son* s2 = dynamic_cast<Son*>(f);     //下行转换必须包含多态,否则编译报错
    Son* s3 = reinterpret_cast<Son*>(f); //Father -> Son
    s1->fun(); //包含多态时都能通过
    s2->fun();
    s3->fun();

    //3、不相关的类型转换
    std::cout << "不相关类转换:\n";
    
    //A* a1 = static_cast<A*>(b);    //error,无效类型转换
    //A* a2 = dynamic_cast<A*>(b);   //error,必须包含多态
    A* a3 = reinterpret_cast<A*>(b); //完全强制类型转换,可转换两个毫无关系的类
    a3->fun();
}

4、类的引用转换测试

都可以转换,但dynamic_cast进行下行转换时会抛出异常

void testClassReference(void) //引用类型转换
{
    A a;
    A& ra = a; //A的引用
    B b;
    B& rb = b; //B的引用
    Father f;
    Father& rf = f; //Father的引用
    Son s;
    Son& rs = s;    //Son的引用

    std::cout << "\n####4、类的引用转换测试####\n";

    //1、上行转换
    std::cout << "上行转换\n";
    rf = static_cast<Father&>(rs);      //ok
    rf.fun();
    rf = dynamic_cast<Father&>(rs);     //ok
    rf.fun();
    rf = reinterpret_cast<Father&>(rs); //ok
    rf.fun();

    //2、下行转换
    std::cout << "下行转换\n";
    rs = static_cast<Son&>(rf);      //ok
    rs.fun();
    rs = dynamic_cast<Son&>(rf);     //ok,会抛出异常,但能转换成功!!!
    rs.fun();
    rs = reinterpret_cast<Son&>(rf); //ok
    rs.fun();

    //3、不相关类型转换
    std::cout << "不相关类转换\n";
    ra = static_cast<A&>(ra);      //ok
    ra.fun();
    ra = dynamic_cast<A&>(ra);     //ok
    ra.fun();
    ra = reinterpret_cast<A&>(ra); //ok
    ra.fun();
}

完整测试代码

test.h

#ifndef __TEST_H
#define __TEST_H

#include <iostream>
#include <functional>
//#define NO_VIRTUAL
using namespace std;

class A
{
public:
    void fun()
    {
        std::cout << "fun A" << "\n";
    }
};

class B
{
public:
    void fun()
    {
        std::cout << "fun B" << "\n";
    }
};

class Father //父类
{
public:
    void fun()
    {
        std::cout << "fun Father\n";
    }

#ifndef NO_VIRTUAL
    virtual void test()
    {
        std::cout << "Father virtual test\n";
    }
#endif
};

class Son : public Father //子类
{
public:
    void fun()
    {
        std::cout << "fun Son\n";
    }

#ifndef NO_VIRTUAL
    void test() override //重写父类方法
    {
        std::cout << "Son virtual test\n";
    }
#endif
};

#endif

test.cpp

#include "test.h"

void testGeneralType(void) //普通类型转换
{
    int a = 0;
    char b = 2;
    int* p = nullptr;
    char* cp = nullptr;
    void* vp = nullptr;

    std::cout << "\n####1、普通类型转换测试####\n";

    //1、char -> int
    a = static_cast<int>(b);        //ok
    //a = dynamic_cast<int>(b);     //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    //a = reinterpret_cast<int>(b); //error,不能转换普通类型

    //2、int -> int*
    //p = static_cast<int*>(a);     //error,无效类型转换
    //p = dynamic_cast<int*>(a);    //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    p = reinterpret_cast<int*>(a);  //ok

    //3、int* -> int
    //a = static_cast<int>(p);     //error,无效类型转换
    //a = dynamic_cast<int>(p);    //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    a = reinterpret_cast<int>(p);  //ok

    //4、char* -> int*
    //p = static_cast<int*>(cp);    //error,无效类型转换
    //p = dynamic_cast<int*>(cp);   //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    p = reinterpret_cast<int*>(cp); //ok

    //5、void* -> int*
    p = static_cast<int*>(vp);      //ok
    //p = dynamic_cast<int*>(vp);   //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    p = reinterpret_cast<int*>(vp); //ok

    //6、int* -> void*
    vp = static_cast<void*>(p);      //ok
    //vp = dynamic_cast<void*>(p);   //error,操作数(object)必须是指向完整类类型的指针
    vp = reinterpret_cast<void*>(p); //ok
}

void testClass(void) //类转换
{
    A a;
    B b;
    Father f;
    Son s;

    std::cout << "\n####2、类的转换测试####\n";

    //1、上行转换
    std::cout << "上行转换:";
    f = static_cast<Father>(s);        //ok
    f.fun();
    //f = dynamic_cast<Father>(s);     //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    //f = reinterpret_cast<Father>(s); //error

    //2、下行转换
    //s = static_cast<Son>(f);      //error,不存在转换规则
    //s = dynamic_cast<Son>(f);     //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    //s = reinterpret_cast<Son>(f); //error,不允许

    //3、不相关类型转换
    std::cout << "不相关类转换:";
    a = static_cast<A>(a);        //ok
    a.fun();
    //a = dynamic_cast<A>(a);     //error,类型<type>必须是指向完整类类型或 void * 的指针或引用
    //a = reinterpret_cast<A>(a); //error,不允许
}

void testClassPointer(void) //类的指针转换
{
    A* a = new A; //A和B是两个毫无关联的类
    B* b = new B;
    Father* f = new Father; //父类
    Son* s = new Son;       //子类

    std::cout << "\n####3、类的指针转换测试####\n";

    //1、上行指针转换
    std::cout << "上行转换:\n";
    Father* f1 = static_cast<Father*>(s);  //Son -> Father
    Father* f2 = dynamic_cast<Father*>(s);
    Father* f3 = reinterpret_cast<Father*>(s);
    f1->fun(); //都能通过
    f2->fun();
    f3->fun();

    //2、下行指针转换
    std::cout << "下行转换:\n";
    Son* s1 = static_cast<Son*>(f);      //可以不包含多态
    Son* s2 = dynamic_cast<Son*>(f);     //下行转换必须包含多态,否则编译报错
    Son* s3 = reinterpret_cast<Son*>(f); //Father -> Son
    s1->fun(); //包含多态时都能通过
    s2->fun();
    s3->fun();

    //3、不相关的类型转换
    std::cout << "不相关类转换:\n";
    
    //A* a1 = static_cast<A*>(b);    //error,无效类型转换
    //A* a2 = dynamic_cast<A*>(b);   //error,必须包含多态
    A* a3 = reinterpret_cast<A*>(b); //完全强制类型转换,可转换两个毫无关系的类
    a3->fun();
}

void testClassReference(void) //引用类型转换
{
    A a;
    A& ra = a; //A的引用
    B b;
    B& rb = b; //B的引用
    Father f;
    Father& rf = f; //Father的引用
    Son s;
    Son& rs = s;    //Son的引用

    std::cout << "\n####4、类的引用转换测试####\n";

    //1、上行转换
    std::cout << "上行转换\n";
    rf = static_cast<Father&>(rs);      //ok
    rf.fun();
    rf = dynamic_cast<Father&>(rs);     //ok
    rf.fun();
    rf = reinterpret_cast<Father&>(rs); //ok
    rf.fun();

    //2、下行转换
    std::cout << "下行转换\n";
    rs = static_cast<Son&>(rf);      //ok
    rs.fun();
    rs = dynamic_cast<Son&>(rf);     //ok,会抛出异常,但能转换成功!!!
    rs.fun();
    rs = reinterpret_cast<Son&>(rf); //ok
    rs.fun();

    //3、不相关类型转换
    std::cout << "不相关类转换\n";
    ra = static_cast<A&>(ra);      //ok
    ra.fun();
    ra = dynamic_cast<A&>(ra);     //ok
    ra.fun();
    ra = reinterpret_cast<A&>(ra); //ok
    ra.fun();
}

int main()
{
    //C++强制类型转换对比测试
    //运行环境 VS2019
    testGeneralType();    //通用类型转换测试
    testClass();          //类转换测试
    testClassPointer();   //类指针转换测试
    testClassReference(); //类的引用转换测试

    /* 总结:
    * 1、普通类型转换
    *   指针和整数之间转换、指针之间转换(void*除外)只能用reinterpret_cast
    *   整数之间转换可以只能用static_cast
    * 2、类之间转换
    *   只能用static_cast,但无法进行下行转换
    * 3、类的指针转换
    *   reinterpret_cast可以任意转换
    *   static_cast和dynamic_cast只能转换具有父子关系的类型指针
    *   其中dynamic_cast进行下行转换时必须包含多态(虚函数)
    * 4、类的引用转换
    *   都可以任意转换
    */

    /* 特性
    * 1、static_cast<type>(object)
    *   相当于传统的C语言里的强制转换,能转换非指针类型类和变量
    * 2、dynamic_cast<type>(object)
    *   只能转换具有父子关系的类指针,而且下行转换还不许包含多态(虚函数)
    *   条件比较苛刻,执行效率不高
    * 3、reinterpret_cast<type>(object)
    *   强制转换一切类型指针,无任何检查,正确性由程序员自己负责
    */

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值