C++ 类型转换
2020 年 06 月 17 日 745 666 字 暂无评论

01.类型转换名称和语法

  • C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:
    • TYPE b = (TYPE)a
  • C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用。
    • static_cast 静态类型转换。如int转换成char
    • reinterpreter_cast 重新解释类型
    • dynamic_cast 命名上理解是动态类型转换。如子类和父类之间的多态类型转换。
    • const_cast, 字面上理解就是去const属性。
  • 4种类型转换的格式:
    • TYPE B = static_cast (a)

02.类型转换一般性介绍

  1. static_cast<>() 静态类型转换,编译的时c++编译器会做类型检查;
    1. 基本类型能转换 但是不能转换指针类型
  2. 若不同类型之间,进行强制类型转换,用reinterpret_cast<>() 进行重新解释
  3. 一般性结论:
    1. C语言中 能隐式类型转换的,在c++中可用 static_cast<>()进行类型转换。因C++编译器在编译检查一般都能通过;
    2. C语言中不能隐式类型转换的,在c++中可以用 reinterpret_cast<>() 进行强行类型 解释。总结:static_cast<>()和reinterpret_cast<>() 基本上把C语言中的 强制类型转换给覆盖
    3. reinterpret_cast<>()很难保证移植性。
  4. dynamic_cast<>(),动态类型转换,安全的基类和子类之间转换;运行时类型检查
  5. const_cast<>(),去除变量的只读属性

03.用法案例

3.1static_cast用法和reinterpret_cast用法

#include <iostream>

using namespace std;

int main()
{
    double dPi = 3.1415926;

    //1静态的类型转换:  在编译的时 进行基本类型的转换 能替代c风格的类型转换 可以进行一部分检查
    int num1 = static_cast<int> (dPi); //c++的新式的类型转换运算符  
    int num2 = (int)dPi;                //c语言的 旧式类型转换 
    int num3 = dPi;                        //隐士类型转换
    cout << "num1:" << num1 << " num2:" << num2 << " num3:" << num3 << endl;

    char test[] = "hello";
    char* p1 = test;
    int* p2 = NULL;
    int* p3 = NULL;
    p2 = (int*)p1;

    //2 基本类型能转换 但是不能转换指针类型
    //p2 = static_cast<int *> (p1); //“static_cast”: 无法从“char *”转换为“int *”

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

    return 0;
}

3.2dynamic_cast用法和reinterpret_cast用法

#include <iostream>

using namespace std;

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

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

        void doSwim()
        {
                cout << "我要狗爬" << endl;
        }
};


class Cat : public Animal
{
public:
        virtual void  cry()
        {
                cout << "miaomiao " << endl;
        }
        void doTree()
        {
                cout << "我要爬树" << endl;
        }

};

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

private:
        int price;

};

void ObjPlay(Animal* base)
{
        base->cry();
        Dog* pDog = dynamic_cast<Dog*>(base);
        if (pDog != NULL)
        {
                pDog->cry();
                pDog->doSwim();
        }

        Cat* pCat = dynamic_cast<Cat*>(base);
        if (pCat != NULL)
        {
                pCat->cry();
                pCat->doTree();
        }
}


int main()
{
        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 Dog());

        return 0;
}

3.3const_cast用法

#include <iostream>

using namespace std;

//典型用法 把形参的只读属性去掉
void Opbuf(const char* p)
{
        cout << p << endl;
        char* p2 = const_cast<char*>(p);
        p2[0] = 'b';
        cout << p << endl;
}

int main()
{

        const char* p1 = "11111111111";

        char test[] = "22222222";
        char* p2 = test;

        char* p3 = const_cast<char*>(p1);
        char buf[100] = "aaaaaaaaaaaa";

        Opbuf(buf);

        //要保证指针所执行的内存空间能修改才行 若不能修改 还是会引起程序异常
        //Opbuf("dddddddddddsssssssssssssss");
        return 0;
}

04.小结

  1. 程序员要清除的知道: 要转的变量,类型转换前是什么类型,类型转换后是什么类型。转换后有什么后果。
  2. 一般情况下,不建议进行类型转换;避免进行类型转换。
  3. 有人说是因为之前的vs版本可以写成char*是历史遗留原因,在vs2017之后,程序可能就崩溃了,新版本VS对这个进行了更严格的控件。可以先用字符数组存储,再给指针用了。

版权属于:zfh

本文链接:http://zfhblog.com/index.php/archives/90/



评论已关闭