我可以使用static_cast进行向下投射吗?

时间:2017-04-23 14:21:47

标签: c++

我正在学习c ++。 我想尝试向下转换一个接口类;虽然我已经学会了铸造可能是由于糟糕的编程设计造成的。

有些网站说"使用dynamic_cast检查向下投射的有效性"。但是,在我的情况下,我不需要检查有效性,因为我可以保证它是从基类到派生类的向下转换。我在以下示例代码中尝试了dynamic_cast和static_cast。而且效果很好。

当我能保证它是一个有效的向下投射时,我可以使用static_cast吗?

示例代码:

struct Parent_Interface {
    virtual ~Parent_Interface() {};
    virtual void print(void) = 0;
};

struct Child : public Parent_Interface {
    virtual ~Child() {};
    void print(void) override {
        std::cout << "Child::print()." << std::endl;
    }
};

void StaticDownCastToChild(Parent_Interface& parent_interface) {
    auto& child0 = static_cast<Child&>(parent_interface);
    std::cout << "StaticDownCastToChild : ";
    child0.print();
}

void DynamicDownCastToChild(Parent_Interface& parent_interface) {
    auto& child0 = dynamic_cast<Child&>(parent_interface);
    std::cout << "DynamicDownCastToChild : ";
    child0.print();
}

void test_static_cast_down_cast(void) {
    Child c;
    StaticDownCastToChild(c);
    DynamicDownCastToChild(c);
}

执行test_static_cast_down_cast()的输出。

StaticDownCastToChild : Child::print().
DynamicDownCastToChild : Child::print().

3 个答案:

答案 0 :(得分:4)

  

有些网站说“使用dynamic_cast检查向下转换的有效性”。但是,在我的情况下,我不需要检查有效性,因为我可以保证它是从基类到派生类的向下转换。

正确。

  

如果我能保证它是一个有效的向下投射,我可以使用static_cast吗?

事实上,你应该,因为它是“免费的”。 dynamic_cast经常涉及一些运行时开销。

但是,您可能希望dynamic_cast放在assert旁边,以便更好地衡量。请记住,这对您的发布版本没有任何影响,但如果出现严重错误,可能会在调试期间为您提供帮助。我职业生涯中一些最令人满意的时刻涉及到一个意外的assert射击,导致一个非常快速的错误修复过程;替代方案可能是几个月的痛苦和猜测!

答案 1 :(得分:3)

  

有些网站说......

不介意某些网站说。标准(working draft)说:

  

类型为“cv1 B”的左值,其中B是类类型,可以强制转换为“引用cv2 D”,其中D是从B派生的类,如果cv2与cv-qualified相同,或者比cv1更高的cv资格。

此外,它包含的示例与您要求的几乎相同:

struct B { };
struct D : public B { };
D d;
B &br = d;

static_cast<D&>(br);            // produces lvalue to the original d object

因此我会说是的,你可以这样做。

这种演员有很多用途。例如,CRTP惯用法是一种情况,您可以确切地知道派生类的类型,并且您不希望通过使用dynamic_cast来检查强制转换是否有效。您的案例可能是另一个案例(如果没有原始代码,很难说)。

答案 2 :(得分:0)

  

如果我能保证它是一个有效的向下投射,我可以使用static_cast吗?

是的,你可以。也就是说,您知道演员表的情况将是有效的,但您无法指定更具体的类型(例如Child&)不应该经常出现。当您知道您总是通过后者时,我无法想到您使用Parent_Interface&代替Child&的原因。