• 博客
  • 音乐
  • 随想
  • 足迹
  • 关于
  • 个人空间
    • 登录
animals
    bg
    都2023年了,还在用C风格的强转吗?
    所属分类:c++
    发布时间:2025-05-19 10:03

    都2023年了,还在用C风格的强转吗?

    C风格

    int a = 1;
    float b = (float)a; // 普通的强转
    float c = float(a); // 函数风格的强转
    

    上面的例子为C风格的强制类型转换----简单粗暴!直接使用"()"括起来即可。 没有类型检查,直接硬转,转的对错全凭程序员的“造化”了。

    在C++中,强制类型转换分为四种,当然在C++中仍然支持C风格的强转,但是C++保留C风格的强转仅仅是为了语言兼容性的考虑。 因此,都2023年了,还在用C风格的强转吗?

    C++中的四种强制类型转换分别用于不同的目的,这四种强制类型转换,每一种都对应着一个名字, C++中这么分是为了提供更丰富的含义和功能以及更好的类型检查机制,方便代码的书写与维护。 因此,都2023年了,还在用C风格的强转吗?

    下面我们来认识一下这四种强制类型转换,有时也称它们为强制类型转换运算符或者强制类型转换操作符。

    static_cast

    称为静态转换,可以理解为正常转换,在编译期间就会进行类型转换的检查, 通常用于相关类型之间的互相转换,主要用于数值类型之间的相互转换。

    enum class Week {
        Mondy = 1,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday,
    };
    
    int a = 1;
    float b = static_cast<float>(a);
    Week day = static_cast<Week>(a);
    

    reinterpret_cast

    称为重新解释转换,也会在编译期间进行类型转换的检查,但是这是一个非常自由且奇怪的类型转换, 使用此转换会将数据以二进制存在的形式进行重新解释。通常用于无关类型的互相转换,也就等于乱转、瞎转、自由转、爱咋转咋转。 使用最多的情况为与void*进行相互转换。

    class Bag {
    public:
        Bag() = default;
        ~Bag() = default;
    
        void Set(int thing) {
            thing_ = thing;
        }
        int Get() {
            return thing_;
        }
    
    private:
        int thing_ = 0;
    };
    
    void Transfer(void *trans) {
        Bag *bag = reinterpret_cast<Bag*>(trans);
        bag->Set(9);
    }
    
    int main() {
        Bag *bag = new Bag();
        Transfer(reinterpret_cast<void*>(bag));
        std::cout << bag->Get() << std::endl;
        delete bag;
        return 0;
    }
    

    dynamic_cast

    称为动态转换,此强制类型转换不会在编译期间进行类型检查,而是在运行时进行类型的识别与检查,通常用于父类型向子类型转换。 dynamic_cast能将父类的指针或者引用安全的转换为子类的指针或者引用,其实是在帮助开发者做安全检查, 不过使用dynamic_cast有个一前提条件,那就是父类中必需至少又一个虚函数! dynamic_cast会在运行时做类型检查,因此类型检查是要付出代价的,不过与安全性相比,这个代价是非常值得的。

    class Base {
    public:
        Base() = default;
        virtual ~Base() = default;
    
        virtual void Play() = 0;
    };
    
    class Player : public Base {
    public:
        Player() = default;
        ~Player() = default;
    
        void Play() override {
            std::cout << "play" << std::endl;
        }
    };
    
    class Test {
    public:
        Test() = default;
        ~Test() = default;
        void Play() {
            std::cout << "test play" << std::endl;
        }
    };
    
    int main() {
        Base *base = new Player();
        Player *player = dynamic_cast<Player*>(base);
        if (player != nullptr) {
            player->Play();
        }
        Test *test = dynamic_cast<Test*>(base);
        if (test != nullptr) { // test is not subclass of Base, so test must is nullptr.
            test->Play();
        }
        delete base;
        return 0;
    }
    

    const_cast

    称为常量转换,const_cast会在编译期间进行类型转换的检查,这个类型转换只能做一件事,不过也就只有const_cast能够做这件事, 那就是将常量指针或者引用转换成非常量指针或者引用,需要注意的是,const_cast只能转换指针或者引用类型,不能转换普通数值类型。 当你的代码里出现了const_cast,那说明你要重新设计一下你的代码了。

    class Test {
    public:
        Test() = default;
        ~Test() = default;
    
        int value = 0;
    };
    
    void Change(const Test &test) {
        Test &change = const_cast<Test&>(test);
        change.value = 1;
    }
    
    int main() {
        Test test;
        std::cout << test.value << std::endl;
        Change(test);
        std::cout << test.value << std::endl;
        return 0;
    }