C++中的类型转换(Type Cast)

一、背景

1)场景1

C语言由于某个强制类型转换出错了,我们需要查找所有代码中相应的强制类型转换,那么会很难寻找。比如:

double num=6.3131;
int solve=(int)num;

原因:想要查找C语言风格的类型转换我们需要查找(这样的括号,但是函数也有啊
解决:C++中设计了4中类型转换,而且给他们每个后面都有单词cast
以后,我们快速定位类型转换,直接用Ctrl+F去寻找cast就好了

2)场景2

原因:由于C++中用基类和子类的指针,实现了多态。有时候,有些不熟悉多态的编码人员,可能会进行强制类型转换,导致项目崩溃。
解决:C++中针对这些,设计了比如dynamic_cast类型转换

二、类型转换总览

  • C++相较C增加的新特性

1)C++中4种类型转换如下

  • static_cast(静态类型转换)
    • 静态类型转换,编译的时c++编译器会做类型检查,基本类型能转换但是不能转换指针类型
  • reinterpreter_cast(重新解释类型转换,interpreter,v.诠释,说明)
    • 若不同类型之间,进行强制类型转换,用reinterpret_cast进行重新解释
  • dynamic_cast(动态类型转换)
    • C++中重要的,安全的基类和子类之间转换,运行时类型检查
  • const_cast(常量类型准换)
    • 去除变量的只读属性

2)一般结论

  • 1.C语言中能隐式类型转换的,在c++中可用static_cast进行类型转换。因C++编译器在编译检查一般都能通过;
  • 2.C语言中不能隐式类型转换的,在c++中可以用reinterpret_cast进行强行类型解释。
  • 3.总结:static_cast和reinterpret_cast基本上把C语言中的 强制类型转换给覆盖,但是reinterpret_cast很难保证移植性。

三、static_cast

代码展示

double pi = 3.1415926;
int num1 = static_cast<int> (pi);//c++的新式的类型转换运算符  
int num2 = (int)pi;//“强制”类型转换 
int num3 = pi;//c语言/C++的“隐式”类型转换
  • 静态的类型转换: 在编译的时进行基本类型的转换 能替代c风格的类型转换,可以进行一部分检查

四、reinterpret_cast

char *p1 = "hello wangbaoming " ;
int *p2 = NULL;
p2 = (int *)p1;
//static_cast对于基本类型可以转换,但是不能转换指针类型!
//编译的时候就会报错:[Error] invalid static_cast from type 'char*' to type 'int*'

//可以使用  reinterpret_cast 进行重新解释 
p2 = reinterpret_cast<int *> (p1);

五、dynamic_cast

#include<bits/stdc++.h>
using namespace std;

class Animal 
{
public:
    virtual void  voice() = 0; 
};


class Dog : public Animal 
{
    public:
        virtual void  voice()
        {
            cout << "汪汪" << endl;
        }

        void doSwim()  
        { 
            cout << "狗游泳" << endl; 
        }
};



class Cat : public Animal
{
    public:
        virtual void  voice()
        {
            cout << "喵喵 " << endl;
        }
        void doTree()  
        { 
            cout << "猫爬树" << endl; 
        }
};




//另一个类群体 
class Book
{
    private:
        int price;

    public:
        void printP()
        {
            cout << price << endl;
        }
};



//对象运行 
void ObjPlay(Animal *base)
{
    base->voice();

    //猫没有转换成功 
    Dog *pDog = dynamic_cast<Dog *>(base);

    if (NULL != pDog)
    {
        pDog->voice();
        pDog->doSwim();
    }


    Cat *pCat = dynamic_cast<Cat *>(base);

    if (NULL != pCat)
    {
        pCat->voice();
        pCat->doTree();
    }
}

int  main()
{
    //基类指针base 
    Animal *base = NULL;


    //1)可以把子类指针赋给 父类指针 但是反过来是不可以的 需要 如下转换
    //pdog = base;  
    Dog *pDog = static_cast<Dog *> (base);


    //2)把base转换成其他 非动物相关的 err
    //比如下面这一行在编译时会出错! 
    //Book *book= static_cast<Book *> (base);


    //3  reinterpret_cast //可以强制类型转换
    Book *book2= reinterpret_cast<Book *> (base);


    //4 dynamic_cast用法
    ObjPlay(new Cat());

    system("pause");
    return 0;
}

运行结果是

喵喵
喵喵
猫爬树

六、const_cast

#include<bits/stdc++.h>
using namespace std;


//典型用法,把形参的只读属性去掉
void Opbuf(const char *p)
{
    cout << p << endl;

    //把形参的只读属性去掉 
    char *p2 = const_cast<char*>(p);

    p2[0] = 'A';
    cout << p << endl;
}


int main()
{
    const char *p1 = "11111111111";
    char *p2 = "333333333";

    //下面就是用法,虽然会显示
    //[Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings] 
    char *p3 = const_cast<char *>(p1);



    //下面 "000000000000"会自动拆解,放入buf数组中 
    char buf[100] = "000000000000";

    Opbuf(buf);

    //要保证指针所执行的内存空间能修改才行 若不能修改 还是会引起程序异常!!!
    //比如下面,因为下面的 "dddddddddddsssssssssssssss"存在常量区 
    //注意和 char buf[100] = "000000000000";区别 
    //    Opbuf("dddddddddddsssssssssssssss");

    system("pause");
    return 0;
}
000000000000
A00000000000

七、总结

  • 1)编码人员要清楚的知道: 要转的变量,类型转换前是什么类型,类型转换后是什么类型。转换后有什么后果。
  • 2)一般情况下,不建议进行类型转换;避免进行类型转换。
  • 比如上面的“把形参的只读属性去掉”,我在C语言编程的时候,本来就是怕别人写的模块修改我传入的参数才用的const,但是这种类型转换会破坏我设计的初衷!