2017-04-23 17 views
2

我正在学习C++。 我想尝试downcast一个接口类;尽管我已经学会了不好的编程设计可能会导致铸造失败。我可以使用static_cast来强制转型吗?

一些网站说:“使用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(). 
+0

使用'static_cast'是推荐的方式。只是关于*任何*演员。 –

+1

CRTP就是一个例子。 – chris

回答

3

有些网站说...

不要介意什么一些网站说。标准(working draft)表示:

类型“CV1 B”,其中B是一个类型,可以转换为输入“参照CV2 d”,其中d是从B来源的类的左值,如果cv2与cv1具有相同的cv资格,或者具有比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。你的情况可能是另一种情况(没有原始代码很难说)。

+0

谢谢你的回答。是的,我想通过一个接口类来创建一个类ContainerAny。我想通过使用接口可以提供的信息将容器元素转换为原始类,例如,element.classType();再一次非常感谢你。 – mora

+0

@mora我很乐意提供帮助。无论如何,有比“classType”方法更好的解决方案。我的两分钱。 ;-) – skypjack

3

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

正确。

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

是。

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

但是,您可能希望将dynamic_cast放在assert的旁边,这是很好的措施。请记住,这对您的发布版本没有任何影响,但如果出现可怕的错误,可能会在调试过程中为您提供帮助。我职业生涯中最令人满意的时刻有一段时间,意外地发生了一个良好的assert发射,导致了一个非常快速的错误修复过程;另一种选择可能是几个月的痛苦和猜测!

+0

谢谢你回答。我想创建一个ContainerAny类,它包含一些基类是接口类的类。我想使用来自接口的类型信息将容器的元素转换为原始类;例如element.type()。所以我希望我可以保证在第一次有效测试后它是有效的向下转换。 – mora

+0

@mora:完美的使用案例。 –

0

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

是的,你可以。这就是说,情况下,您知道投将是有效的,但你不能指定更具体的类型(例如Child&)应该没有拿出非常频繁。我想不出你会使用Parent_Interface&代替Child&当你知道你总是通过后者的理由。

+1

常见的,当你有某种类型的实体注册界面,你需要“撤消”基于一些非关键型的类型擦除。 –

+0

@Caleb:我尽量让一类ContainerAny持有一些类,其基类是一个接口类。我想将容器的元素转换为原始类。 – mora

+0

叫它......;) –

相关问题