C++类型转换(static_cast和dynamic_cast)
C++ 的类型转换分为两种,分别是静态类型转换(static_cast)和动态类型转换(dynamic_cast),本节带大家分别了解它们的特性和用法。
static_cast 的特点是不改变表达式的 const、volatile 或 __unaligned 属性。static_cast 通常较安全,因为它仅允许编译时可以确定的类型转换。
注意,在类之间的静态类型转换中,需要确保父类至少与目标类型具有兼容性;如果两个类之间没有任何关系,尝试进行转换将导致编译错误。
静态类型转换的主要用途有以下几个方面:
下面是一个使用 static_cast 进行安全的基本类型转换的示例。在 C++ 中,向上转型是指将派生类的指针或引用转换为基类的指针或引用。这通常在多态性中使用,允许通过基类的指针或引用调用在派生类中实现的方法。
这个示例展示了如何在实际程序中应用向上转型,以及 static_cast 在实现多态中的重要性。
但是,虽然 dynamic_cast 提供了类型转换的安全性,但不当使用仍可能导致性能问题或逻辑错误,应仅在确实需要利用多态性进行类型转换时使用。
dynamic_cast 只适用于含有至少一个虚函数的类的指针或引用的转换。这是因为 RTTI 需要通过虚函数表来存取类型信息。如果类没有虚函数,编译器通常不生成类型信息,导致 dynamic_cast 无法执行。
dynamic_cast的主要用途有以下几个方面:
下面是一个使用 ynamic_cast 进行多态类型的安全向下转型的示例:
这个示例展示了向下转型在实现多态时的重要性及其潜在风险,以及如何通过 dynamic_cast 保证转换的安全性。
C++静态类型转换(static_cast)
static_cast<type-id>(expression)
运算符用于将表达式 expression 转换为 type-id 类型,这种转换没有运行时类型检查,主要用于基本数据类型之间的转换、非多态类型的转换,以及类层次结构中父类与子类之间的转换。static_cast 的特点是不改变表达式的 const、volatile 或 __unaligned 属性。static_cast 通常较安全,因为它仅允许编译时可以确定的类型转换。
注意,在类之间的静态类型转换中,需要确保父类至少与目标类型具有兼容性;如果两个类之间没有任何关系,尝试进行转换将导致编译错误。
静态类型转换的主要用途有以下几个方面:
- 类型间转换:实现基本数据类型之间的转换,如从 float 转换为 int,尽管这可能会导致精度损失;
- 类指针和引用转换:在有继承关系的类之间,可以将子类的指针或引用转换为父类(向上转换),这是安全的。反向转换(父类转为子类,即向下转换)则不安全,因为子类可能包含父类所没有的字段或方法;
- 非基本类型转换:可以使用 static_cast 将非 const 对象的类型转换为具有 const 属性的新类型。这种转换结果是一个类型为 const 的新表达式;反之,如果需要从 const 类型移除 const 属性,则必须使用 const_cast 转换符;
- 特殊类型转换:允许将任何类型的表达式转换为 void 类型;
下面是一个使用 static_cast 进行安全的基本类型转换的示例。在 C++ 中,向上转型是指将派生类的指针或引用转换为基类的指针或引用。这通常在多态性中使用,允许通过基类的指针或引用调用在派生类中实现的方法。
#include <iostream> // 基类 class Base { public: virtual void display() const { // 虚函数以支持多态 std::cout << "Display Base class" << std::endl; } virtual ~Base() {} // 虚析构函数以支持多态 }; // 派生类 class Derived : public Base { public: void display() const override { // 重写基类的虚函数 std::cout << "Display Derived class" << std::endl; } }; int main() { Derived d; // 派生类对象 Base* b = &d; // 自然向上转型,无须显式转换 // 调用 Derived 的 display,展示多态性 b->display(); // 使用 static_cast 进行显式向上转型 Derived d2; Base* b2 = static_cast<Base*>(&d2); // 同样调用 Derived 的 display b2->display(); return 0; }运行结果为:
Display Derived class
Display Derived class
- Base 是基类,具有一个虚函数 display(),允许派生类 Derived 进行覆盖。这是实现多态的关键;
- 在 main() 函数中,我们创建了一个 Derived 类的对象 d,然后将它的地址赋给 Base 类型的指针 b。这种自然的向上转换是安全的,因为每个 Derived 对象也是一个 Base 对象;
- 虽然直接赋值已经足够,但如果需要显式转换,可以使用 static_cast 来实现。这显示了 static_cast 的正确使用场合之一——进行安全的向上转型。
这个示例展示了如何在实际程序中应用向上转型,以及 static_cast 在实现多态中的重要性。
C++动态类型转换(dynamic_cast)
dynamic_cast<type_id>(expression)
用于在类层次结构中进行类型转换,主要用于处理多态类型,它能在运行时检查类型转换的合法性。这种检查是通过类的类型信息(通常是类的虚表中的信息)来实现的,因此只适用于至少有一个虚函数的类(即多态类)。但是,虽然 dynamic_cast 提供了类型转换的安全性,但不当使用仍可能导致性能问题或逻辑错误,应仅在确实需要利用多态性进行类型转换时使用。
dynamic_cast 只适用于含有至少一个虚函数的类的指针或引用的转换。这是因为 RTTI 需要通过虚函数表来存取类型信息。如果类没有虚函数,编译器通常不生成类型信息,导致 dynamic_cast 无法执行。
dynamic_cast的主要用途有以下几个方面:
- 安全的向下转型:dynamic_cast 允许将基类指针或引用安全地转换为派生类指针或引用。如果转换合法(即运行时类型匹配),则转换成功;如果不合法,对于指针返回 nullptr,而对于引用抛出 std::bad_cast 异常。
- 向上转型:绝大部分情况 static_cast 执行这一转换已经足够,这也是推荐的操作。不过在多重继承的复杂情形中,dynamic_cast 提供了额外的安全性,因为它会在运行时确认类型的实际兼容性。
下面是一个使用 ynamic_cast 进行多态类型的安全向下转型的示例:
#include <iostream> #include <stdexcept> // 引入标准异常库 // 基类 class Base { public: virtual void display() const { // 虚函数以支持多态 std::cout << "Display Base class" << std::endl; } virtual ~Base() {} // 虚析构函数以支持多态 }; // 派生类 class Derived : public Base { public: void display() const override { // 重写基类的虚函数 std::cout << "Display Derived class" << std::endl; } void specificFunction() const { std::cout << "Specific function for Derived class" << std::endl; } }; int main() { Base* b = new Derived(); // 向上转型,安全 Derived* d; // 尝试向下转型 d = dynamic_cast<Derived*>(b); if (d != nullptr) { d->display(); // 成功转换,调用派生类的方法 d->specificFunction(); // 调用派生类特有的方法 } else { std::cout << "Conversion failed." << std::endl; } delete b; // 释放资源 return 0; }运行结果为:
Display Derived class
Specific function for Derived class
- Base 是基类,带有一个虚函数 display(),而Derived是它的派生类,不仅重写了 display(),还增加了一个特有的方法 specificFunction();
- 通过 dynamic_cast 尝试将基类指针 b 向下转换为派生类指针 d。这个转换检查 b 是否真的指向一个 Derived 类型的对象;
- 如果转换成功(d 不是 nullptr),则可以安全地调用派生类的方法;如果转换失败,d 将是 nullptr,示例中将打印 "Conversion failed."。
这个示例展示了向下转型在实现多态时的重要性及其潜在风险,以及如何通过 dynamic_cast 保证转换的安全性。
相关文章
- C++强制类型转换运算符(static_cast、reinterpret_cast、const_cast和dynamic_cast)
- C++ static_cast、dynamic_cast、const_cast和reinterpret_cast(四种类型转换运算符)
- C++类型转换函数:将当前类的类型转换为其它类型
- C/C++类型转换的本质(经典之作)
- C#数据类型转换
- C#数据类型转换(3种方法)
- C语言类型转换详解(自动类型转换和强制类型转换)
- C#数据类型转换详解(隐式转换和显式转换)
- C#数据类型转换(Parse()、TryParse()和Convert类)
- C语言自动类型转换和强制类型转换详解