四个强制类型转换reinterpret_castconst_caststatic_cast dynamic_cast及比较

四个强制类型转换reinterpret_cast/const_cast/static_cast /dynamic_cast及比较

reinterpret_cast

reinterpret_cast 是一种 C++ 转换运算符,允许程序员在不更改原始对象的情况下将指针或引用转换为不同的类型。 它是一个非常强大且具有潜在危险的运算符,应谨慎使用。

reinterpret_cast 运算符可用于在指针和不相关类型的引用之间进行转换,或将数据对象的位重新解释为不同的类型。 这是一个例子:

int i = 42;
float* fp = reinterpret_cast(&i);

在此示例中,我们有一个值为 42 的整数“i”。然后我们使用“reinterpret_cast”创建一个指向浮点数“fp”的指针,它获取“i”的地址并将其视为指向“浮点数”的指针。 这意味着 fp现在指向与i相同的内存位置,但将i的位视为float`

请注意,reinterpret_cast 不执行任何类型检查或转换。 它只是将对象的位重新解释为不同的类型。 这意味着错误地使用“reinterpret_cast”会导致未定义的行为,例如读取或写入无效的内存位置。

因此,“reinterpret_cast”只应在绝对必要时使用,并且要透彻了解所涉及的类型和潜在风险。

const_cast

const_cast 是一种 C++ 转换运算符,允许程序员删除或添加变量或对象的常量。 当程序员想要修改声明为“const”的变量或对象,或将“const”添加到非 const 变量或对象时,会使用它。

这是一个例子:

void print(int* ptr) {
    std::cout << *ptr << std::endl;
}

int main() {
    const int i = 42;
    const int* ptr = &i;
    int* ptr2 = const_cast(ptr);
    *ptr2 = 7;
    print(const_cast(ptr));
    return 0;
}

在此示例中,我们有一个值为 42 的常量整数“i”和一个指向“i”的指针“ptr”。 我们使用 const_cast 创建一个非常量指针 ptr2 指向与 ptr 相同的内存位置。 然后我们通过将 ptr2 设置为 7 来修改 i 的值。

print 函数接受一个指向整数的非常量指针并打印它的值。 我们再次使用 const_cast 将 ptr(常量指针)传递给 print。

请注意,使用 const_cast 修改 const 对象可能很危险,应谨慎操作。 修改 const 对象可能会导致未定义的行为和意外结果,因此只有在必要时才应该这样做。

static_cast

static_cast 是一种 C++ 转换运算符,允许程序员执行已知在编译时安全的类型转换。 它可用于相关类型之间的转换,例如将派生类指针转换为基类指针,或执行算术转换,例如将整数转换为浮点数。

这是一个例子:

int main() {
    int i = 42;
    float f = static_cast(i);
    std::cout << f << std::endl;

    Base* base = new Derived();
    Derived* derived = static_cast(base);
    derived->doSomething();

    return 0;
}

在此示例中,我们有一个值为 42 的整数“i”。我们使用“static_cast”将“i”转换为浮点数“f”,这是安全的,结果是“f”的值为 42.0。

我们还有一个基类“Base”和一个派生类“Derived”,并创建一个“Derived”类型的新对象并将其赋值给一个“Base*”类型的指针。 然后我们使用 static_castBase* 指针转换为 Derived* 指针,这是安全的,因为我们知道指向的对象实际上是一个 Derived 对象。 然后我们可以通过 Derived* 指针调用 Derived 类的 doSomething() 函数。

请注意,static_cast 是一个编译时运算符,因此它无法执行运行时安全检查。 仅当程序员确定转换是安全的时才应使用它。 如果对转换的安全性有任何疑问,则应改用“dynamic_cast”。

dynamic_cast

dynamic_cast 是一种 C++ 转换运算符,它允许程序员在运行时执行多态类型的安全向下转换。 当需要将基类指针或引用转换为派生类指针或引用时使用它,但程序员不确定转换是否安全。

这是一个例子:

class Base {
public:
    virtual void doSomething() {
        std::cout << "Base doing something" << std::endl;
    }
};

class Derived : public Base {
public:
    void doSomething() override {
        std::cout << "Derived doing something" << std::endl;
    }
};

int main() {
    Base* base = new Derived();
    Derived* derived = dynamic_cast(base);
    if (derived) {
        derived->doSomething();
    } else {
        std::cout << "Invalid cast" << std::endl;
    }
    delete base;
    return 0;
}

在这个例子中,我们有一个基类“Base”和一个派生类“Derived”。 我们创建一个 Derived 类型的新对象,并将其分配给 Base* 类型的指针。 然后我们使用 dynamic_castBase* 指针转换为 Derived* 指针。 如果转换成功,我们通过 Derived* 指针调用 Derived 类的 doSomething() 函数。 如果转换不成功,我们会打印一条错误消息。

请注意,dynamic_cast 是一个运行时运算符,因此它可以执行检查以确保转换是安全的。 只有在至少具有一个虚函数的多态类上使用“dynamic_cast”才是安全的。 此外,dynamic_cast 只能用于转换指针或引用,不能用于转换对象。

如果转换不安全,dynamic_cast 为指针返回一个空指针或为引用抛出 std::bad_cast 异常。 因此,在使用指针或引用之前检查“dynamic_cast”的结果很重要。

比较

reinterpret_castconst_caststatic_castdynamic_cast 都是用于类型转换的 C++ 转换运算符。 但是,它们在功能和用法上有所不同:

  • reinterpret_cast 是一个非常强大的低级运算符,允许程序员重新解释对象的位,就好像它是不同的类型一样。 它用于在不相关类型的指针和引用之间进行转换,或者将数据对象的位重新解释为不同的类型。 它不执行任何类型检查或转换,应谨慎使用。

  • const_cast 用于删除或添加变量或对象的 const-ness。 它用于修改声明为 const 的变量或对象,或将 const 添加到非 const 变量或对象。

  • static_cast 用于执行已知在编译时安全的安全类型转换。 它可用于相关类型之间的转换,例如将派生类指针转换为基类指针,或执行算术转换,例如将整数转换为浮点数。

  • dynamic_cast 用于在运行时执行多态类型的安全向下转换。 当需要将基类指针或引用转换为派生类指针或引用时使用它,但程序员不确定转换是否安全。 它执行运行时检查以确保转换是安全的,并返回空指针或抛出 std::bad_cast 异常(如果不是)。

通常,应谨慎使用 reinterpret_castconst_cast,因为如果使用不当,它们很容易导致未定义的行为。 在执行已知在编译时安全的类型转换时,static_cast 是更安全的选择,而在运行时执行多态类型的向下转换时,dynamic_cast 是最安全的选择。

你可能感兴趣的:(C++,笔记,c++)