2012-05-01 49 views
3

心中已经问这些问题,前一段时间: Multiple inheritance casting from base class to different derived classC++运行时检查,如果对象实现了接口

但我还是不知道我理解的答案。 现在的问题是:下面的代码是否有效?

#include <iostream> 

using namespace std; 

struct Base 
{ 
    virtual void printName() 
    { 
     cout << "Base" << endl; 
    } 
}; 

struct Interface 
{ 
    virtual void foo() 
    { 
     cout << "Foo function" << endl; 
    } 
}; 

struct Derived : public Base, public Interface 
{ 
    virtual void printName() 
    { 
     cout << "Derived" << endl; 
    } 
}; 

int main(int argc, const char * argv[]) 
{ 
    Base *b = new Derived(); 
    Interface *i = dynamic_cast<Interface*>(b); 
    i->foo(); 

    return 0; 
} 

该代码正常工作。但据我了解,根据上一个问题,它不应该。所以我不确定这样的代码是否有效。谢谢!

+0

您对上一个问题的回答中的注释确实解释了'dynamic_cast'将适用于您的案例。 – Chad

回答

4

它是有效的代码。

为什么?
因为dynamic_cast会告诉您所指向的对象是否实际上是要投射到的类型。
在这种情况下实际的对象被指向是类型Derived的类型和Derived的每个对象的类型是Interface(由于从InterfaceDerived继承),因此dynamic_cast是有效的也和它的工作原理。

+0

与我以前的问题有什么不同? (真的不明白) – Andrew

+0

@Andrew:没有什么区别,Emilio Garavaglia在上一个问题中给出了同样的答案。 – interjay

+2

@Andrew:'dynamic_cast'只有在类中至少有一个'virtual'方法(又名多态类)时才有效。见[this](http://stackoverflow.com/questions/4227328/faq-why-does-如果一个类至少有一个虚拟方法,则动态转换只能工作)。您的前一个示例没有任何“虚拟”方法,因此无法使用“dynamic_cast”。 –

0

如果dynamic_cast成功,那么它是有效的。它已经在运行时执行类型安全检查。

+0

虽然在这种情况下情况确实如此,但我不喜欢设置“如果它有效,这是正确的”的先例。 – Chad

+0

,因为它是'dynamic_cast',这就是论点。我不想重新解释SO – UmNyobe

+0

@UmNyobe上十多个已知问题中出现的问题:OP所具有的问题是*它为什么有效?*答案不是因为'dynamic_cast'这么说。他已经知道'dynamic_cast'是这么说的(OP提供了一个很好的示例代码来演示它)真正的q是*为什么'dynamic_cast'有效?* –

2

只要涉及的类至少有一个虚拟方法(它可能是一个虚拟析构函数),那么使用dynamic_cast就是正确的,并且可以用于一致性编译器。

static_cast不同,dynamic_cast可以允许运行时检查类型信息。但是,这也意味着它可能会失败,并在使用它投掷指针时返回NULL。如果有可能不成功,应检查演员结果。

在你问的前一个问题中,这些类没有任何虚拟方法,因此不起作用,因为dynamic_cast不能用于这样的类。

0

考虑以下几点:

Base *b = new B(); 
Interface *i = dynamic_cast<Interface *>(b); 

如若这项工作?号为什么,因为BaseInterface彼此没有关系。但是,在指向Base的指针指向也是从Interface派生的对象的特殊情况下,您可以投射(读取:哄编译器考虑该对象的类型为InterfaceBase指针,并使用进一步运营商dynamic_cast

0

你的代码是有效的,因为标准是这样说的5.2.7条第4款(C++ 2003标准):

运行时检查逻辑的执行过程如下:

- 如果在大多数派生对象通过v,v点(引用)指向(引用)T对象的公共基类子对象,并且如果只有一个类型为T的对象从指向(引用)的子对象派生v,结果是一个指向T对象的指针(左值)。否则,如果v指向(派生)大多数派生对象的公共基类子对象,并且最派生对象的类型具有T类型的基类,并且该派生类型是明确的且公有的,结果是一个指向最左派对象的T子对象的指针(左值)。

- 否则,运行时检查失败。

请注意在运行时检查中使用“大多数派生对象”。在你的例子中,你的Base *b对象的“最派生对象”是一个Derived对象。由于类DerivedBaseInterface都公开继承,所以在这种特定情况下,该对象可以转换为Interface*

相关问题