dynamic_cast conversion

安全的转换指针和引用到父类,子类,并且死沿着一侧的继承关系。

格式

dynamic_cast < new-type > ( expression )

其中,

new-type---指向一个完备的class类型的指针,或一个完备的class类型的引用,或者是指向void的指针。

expression---如果新的类型是一个引用,则是一个完备的class类型的lvalue或glvalue。如果新的类型是一个指针,则是一个指向完备的class类型的指针的prvalue。

如果cast成功,则dynamic_cast返回的是new-type类型的值。如果cast失败且new-type是一个指针类型,它会返回一个该类型的NULL指针。如果cast失败且new_type是一个引用类型,它会抛出一个异常,该异常是std::bad_cast的句柄。

解释

只有如下的转换能使用dynamic_cast来完成,(除了某些带有constness或volatility的转换)。

1)如果expression的类型正好是new_type或者是new_type的“ less cv-qualified ”版本(即不带const和volatile的类型),运算的结果就是这个expression的值,类型是new_type。

2)如果express的值是一个NULL指针,结果就是该new_type类型的NULL指针值。

3)如果new_type是base的指针或引用,并且expression的类型是衍生类的指针或引用,该衍生类的基类是唯一的、可访问的;那么, 运算的结果是基类子对象的指针或引用,该对象是由expression指向或标识的衍生类对象。(说明:该情况下,隐含的转换和static_cast的作用是相同的)。

4)如果expression是一个指向多态类型的指针,并且new_type是指向void指针,结果是一个指针,该指针指向衍生层级最高的对象,由expression指向或引用

5)如果expression是指向多态类型基类的指针或引用,并且new_type是衍生类的指针或引用;那么,会执行运行时检查

a) 大多数expression指向或引用的衍生类对象是检查过的。如果,一个对象,expression指向或引用到衍生类的公共基类,并且只要衍生类类型的一个对象是从express指向或引用的子对象衍生出来的;那么,cast的结果就是指向或引用那个衍生类的对象。这就是通常所说的downcast(向下类型转换)

b)否则,如果expression指向或引用到最高层次的衍生类的公共基类,并且,同时,最高层次的衍生类的对象有一个明确的衍生类的公共基类,cast的结果是指向或引用那个最高层次的衍生类的对象。这就是所说的“sidecast”。

c)否则,运行时检查失败。如果dynamic_cast作用到指针上,则返回 new-type类型的NULL指针值。如果是引用,则抛出std::bad_cast异常。

6)当dynamic_cast被用在构造或析构函数(直接或间接),并且expression引用的是当前正在构造或析构的对象,那么,该对象会被认为是最高层次的对象。如果new_type不是该构造或析构函数的自己的class或自己的class的基类的指针或引用,那么,这个行为是未定义的。

Similar to other cast expressions, the result is:

  • an lvalue if new-type is an lvalue reference type (expression must be an lvalue)
  • an xvalue if new-type is an rvalue reference type (expression may be lvalue or rvalue (until C++17)must be a glvalue (prvalues are materialized) (since C++17) of a complete class type)
  • a prvalue if new-type is a pointer type

说明

  • A downcast can also be performed with static_cast, which avoids the cost of the runtime check, but it's only safe if the program can guarantee (through some other logic) that the object pointed to by expression is definitely Derived.
  • Some forms of dynamic_cast rely on runtime type identification (RTTI), that is, information about each polymorphic class in the compiled program. Compilers typically have options to disable the inclusion of this information.

Keywords

dynamic_cast

举例

#include <iostream>
 
struct V {
    virtual void f() {};  // must be polymorphic to use runtime-checked dynamic_cast
};
struct A : virtual V {};
struct B : virtual V {
  B(V* v, A* a) {
    // casts during construction (see the call in the constructor of D below)
    dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B*
    dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B
  }
};
struct D : A, B {
    D() : B(static_cast<A*>(this), this) { }
};
 
struct Base {
    virtual ~Base() {}
};
 
struct Derived: Base {
    virtual void name() {}
};
 
int main()
{
    D d; // the most derived object
    A& a = d; // upcast, dynamic_cast may be used, but unnecessary
    D& new_d = dynamic_cast<D&>(a); // downcast
    B& new_b = dynamic_cast<B&>(a); // sidecast
 
 
    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
    }
 
    Base* b2 = new Derived;
    if(Derived* d = dynamic_cast<Derived*>(b2))
    {
        std::cout << "downcast from b2 to d successful\n";
        d->name(); // safe to call
    }
 
    delete b1;
    delete b2;
}

 

Output:

downcast from b2 to d successful

 

See also

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值