标准的C++中是否有safe_cast?

7

看起来 Visual C++ 中有一个 safe_cast,它类似于 dynamic_cast。

我想知道 safe_cast 是否在标准的 C++ 中?


1
你的 safe_cast 会做什么 dynamic_cast 做不到的呢? - KillianDS
1
safe_cast 在无效转换时会抛出异常,就像在 Java 中进行转换一样。而 dynamic_cast 则会返回 NULL 指针而不会失败。 - Bartosz Przybylski
1
&dynamic_cast<Foo&>(*p) - Alan Stokes
1
@Bartek...而dynamic_cast需要RTTI,因此您可能需要处理一些编译器标志以确保获得正确的行为,并且它会在运行时花费一些成本,因为它发生在运行时。 - user2485710
3个回答

8

safe_cast在C++/CLI中使用。C++中没有这样的标准构造。


3

safe_cast不是标准的C++类型转换方式。只有4个转换操作符可用。

1.dynamic_cast <new_type> (expression)
2.reinterpret_cast <new_type> (expression)
3.static_cast <new_type> (expression)
4.const_cast <new_type> (expression)

在C++11中,也有std::movestd::forward,它们都是在编译时发生的转换。 - user2485710
1
@user 但它们不是语言内置的运算符,只是函数。 - Alan Stokes
1
@AlanStokes 标准库之所以被称为“标准”,是有原因的...你可以将标准库的任何部分视为C++标准的一部分,仅仅因为有一个ISO文件来统治它们。 - user2485710
2
@user 库/语言的区分仍然有用(我认为自由模式仍然存在,这使事情变得复杂)。我想说的是,虽然 std::move 非常有用,而且显然是通过转换实现的,但它并不是技术上的转换运算符。 - Alan Stokes

0
我自己需要一个“安全”的转换,后来在 boost::polymorphic_cast 中找到了我想要的。当转换无效或从 nullptr 进行转换时,它会抛出异常。如果类型不是多态的(即没有虚成员),它会在编译时报错。
#include <iostream>
#include <boost\polymorphic_cast.hpp>

class Base{
    public: virtual ~Base() = default;
};

class D1 : public Base{
    public: virtual ~D1() = default;
};

class D2 : public Base{
    public: virtual ~D2() = default;
};


int main(void)
{
    D1 d1;
    Base* b = &d1;
    Base* b2 = nullptr;

    std::cout << "\n---Testing valid cast---\n";
    std::cout << "cast from base to d1: " << boost::polymorphic_cast<D1*>(b) << "\n";

    try {
        std::cout << "\n---Testing invalid cast---\n";
        std::cout << "base to d2: " << boost::polymorphic_cast<D2*>(b) << "\n";
    }
    catch (...) {
        std::cout << "cast from based to d2 failed\n";
    }

    try {
        std::cout << "\n---Testing nullptr cast---\n";
        std::cout << "null to d1: " << boost::polymorphic_cast<D1*>(b2) << "\n";
    }
    catch (...) {
        std::cout << "cast from null to d1 failed\n";
    }
}

输出结果为:

---Testing valid cast---
cast from base to d1: 00AFFBD4

---Testing invalid cast---
cast from based to d2 failed

---Testing nullptr cast---
cast from null to d1 failed

1
换句话说,&std::dynamic_cast<D1&>(*b)?(当然,你得自己处理 NULL 情况)。这并不是真正的 safe_cast,只是 dynamic_cast 的抛出版本加上了空指针检查。 - Lightness Races in Orbit
据我所知,这正是 safe_cast 的作用,如果转换无效(而不是给您未定义的行为),则会抛出异常,以便您可以捕获并恢复。这是一种明确定义的行为,因此我会称其为“安全”。它可以避免您编写需要使用 dynamic_cast 的 if/else 语句。这也是 C++/CLI 的 safe_cast 所做的事情(https://learn.microsoft.com/en-us/cpp/windows/safe-cast-cpp-component-extensions?view=vs-2017),这也是 OP 所要求的。 - opetroch
我怀疑safe_cast 的主要区别在于它适用于 C++/CLI 类型 ;) 因此,在 C++ 中并不是真正的因素。无论如何,我想我的观点是 Boost 对此来说过于复杂了;标准库已经有(基本上)可以满足您需求的东西了,虽然包装它以检查 NULL 可能会很有用,并且可以获得您所描述的内容。 - Lightness Races in Orbit
很好,如果我还没有使用boost,我不会仅仅为了这个而使用它 :) 如果你已经在使用boost,那么使用它代替自己编写的版本可能是有意义的。 - opetroch
可能是这样,但对于读者来说,使用简单的 dynamic_cast 仍然更清晰明了。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接