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

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

  • 0、总结
  • 1、普通类型转换测试
  • 2、类转换测试
  • 3、类的指针转换测试
  • 4、类的引用转换测试
  • 完整测试代码

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(b);     //error,类型必须是指向完整类类型或 void * 的指针或引用
    //a = reinterpret_cast(b); //error,不能转换普通类型

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

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

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

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

    //6、int* -> void*
    vp = static_cast<void*>(p);      //ok
    //vp = dynamic_cast(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(s);     //error,类型必须是指向完整类类型或 void * 的指针或引用
    //f = reinterpret_cast(s); //error

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

    //3、不相关类型转换
    std::cout << "不相关类转换:";
    a = static_cast<A>(a);        //ok
    a.fun();
    //a = dynamic_cast(a);     //error,类型必须是指向完整类类型或 void * 的指针或引用
    //a = reinterpret_cast(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(b);    //error,无效类型转换
    //A* a2 = dynamic_cast(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 
#include 
//#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(b);     //error,类型必须是指向完整类类型或 void * 的指针或引用
    //a = reinterpret_cast(b); //error,不能转换普通类型

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

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

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

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

    //6、int* -> void*
    vp = static_cast<void*>(p);      //ok
    //vp = dynamic_cast(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(s);     //error,类型必须是指向完整类类型或 void * 的指针或引用
    //f = reinterpret_cast(s); //error

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

    //3、不相关类型转换
    std::cout << "不相关类转换:";
    a = static_cast<A>(a);        //ok
    a.fun();
    //a = dynamic_cast(a);     //error,类型必须是指向完整类类型或 void * 的指针或引用
    //a = reinterpret_cast(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(b);    //error,无效类型转换
    //A* a2 = dynamic_cast(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(object)
    *   相当于传统的C语言里的强制转换,能转换非指针类型类和变量
    * 2、dynamic_cast(object)
    *   只能转换具有父子关系的类指针,而且下行转换还不许包含多态(虚函数)
    *   条件比较苛刻,执行效率不高
    * 3、reinterpret_cast(object)
    *   强制转换一切类型指针,无任何检查,正确性由程序员自己负责
    */

    return 0;
}

你可能感兴趣的:(c++)