静态和动态演员之间的区别

时间:2014-10-04 07:33:37

标签: c++ dynamic-cast static-cast

这个类是多态的。 为什么两者都打印相同的输出?

class A
{
public:
    virtual void P(){ cout << "A" << endl; }

};
class B : public A
{
public:
    void P()override{
        cout << "B" << endl;
    }
    B(){ cout << "Created B" << endl; s = "Created by B"; }
    string s;
};

主要: 变式1:

A* a = new B();    // Created B
B* b = static_cast<B*>(a);
b->P();    B
cout<<b->s<<endl;  // Created by B

变种2:

A* a = new B();
    B* b = dynamic_cast<B*>(a);
    if (b){
        b->P();
        cout << b->s << endl;  // Prints same
    }

2 个答案:

答案 0 :(得分:8)

你的两个例子都会做同样的事情,那很好。请尝试使用此功能:

A* a = new A();

在这种情况下,static_cast将“成功”(虽然它是未定义的行为),而dynamic_cast将“失败”(通过返回nullptr,您已经检查过)。

您的原始示例没有显示任何有趣的内容,因为它们都成功并且是有效的演员。与dynamic_cast的区别在于它允许您检测无效的强制转换。

如果您想了解 dynamic_cast如何做到这一点,请阅读RTTI,运行时类型信息。这是一些额外的簿记,C ++在某些情况下会检查对象的类型(这对于此很重要,如果你使用typeid())。

答案 1 :(得分:1)

在这种情况下,static_cast在语义上等同于dynamic_cast

  

static_cast&lt; new_type &gt; (表达

     

2)如果 new_type 是某个D类和D类的指针或引用   表达式的类型是指向其非虚拟基础的指针或引用   B,static_cast执行向下转发。这样的static_cast没有   运行时检查以确保对象的运行时类型实际为D,   并且只有在这个前提条件得到保证的情况下才可以安全使用   其他方法,例如实现静态多态时。安全   可以使用dynamic_cast进行向下转换。

     

dynamic_cast&lt; new_type &gt; (表达

     

5)如果表达式是多态类型Base的指针或引用,   new_type是运行时类型Derived的指针或引用   执行检查:

     
    

a)表达式指向/标识的派生对象最多     检查。如果,在该对象中,表达式指向/指向公众     Derived的基数,如果只导出Derived类型的一个子对象     从表达式指向/标识的子对象,然后是结果     施法点/指的是Derived子对象。 (这被称为     一个“垂头丧气”。)

         

[...]

         

c)否则,运行时检查失败。如果     dynamic_cast用于指针,类型的空指针值     返回 new_type 。如果它用于引用,则例外     std::bad_cast被抛出。

  

最后一个条款使dynamic_cast更安全,因为你可以检查演员表是否不成功:

Base* b1 = new Base;
if(Derived* d = dynamic_cast<Derived*>(b1))
{
    std::cout << "downcast from b1 to d successful\n";
    d->name(); // safe to call
}