errorman

不积跬步,无以至千里

导航

dynamic_cast

Posted on 2023-03-27 21:10  Clemens  阅读(24)  评论(0编辑  收藏  举报

Safely converts pointers and references to classes up, down, and sideways along the inheritance hierarchy.

沿继承层次结构将指针和引用安全地向上、向下和横向转换为类。

dynamic_cast<dest>(src)

dest和src都必须为指针或者引用。如果运行时src和dest所引用的对象,是相同类型,或者存在is-a关系(public继承),则转换成功;否则转换失败。dynamic_cast只能用来转换多态类型(即定义了虚函数)的对象的指针或引用。如果操作数是指针,成功则返回目标类型的指针,失败返回NULL。如果操作数是引用,成功则返回目标类型的引用,失败抛出std::bad_cast异常。

dynamic_cast的“运行时类型的转换匹配”,是通过维护一棵由type_info类型对象作为节点的类型继承关系的树,遍历这棵继承树来确定一个待转换的对象的类型和目标类型之间是否存在is-a关系。

 

向上转换,可以,但没必要

class B
{
public:
    int b;
};
class C : public B
{
public:
    int c;
};
class D : public C
{
};
int main()
{
    D* d = new D();
    d->c = 10;
    d->b = 11;
    C* pc = dynamic_cast<C*>(d); //ok,pc指向d的C子对象,但没必要
    B* pb = dynamic_cast<B*>(d); //OK,B是D的间接基类,pb指向d的B子对象,但没必要
    delete d;
}

这种类型的转换称为“向上转换”,因为它根据继承结构将指针向上移动类层次结构,从派生类到它的派生类。 upcast 是一种隐式转换。

 

dest 为 void*

则进行运行时检查以确定表达式的实际类型。结果是指向表达式指向的完整对象的指针。例如:

class A { virtual void f() {} };
class B { virtual void f() {} };

int main() {
	A* pa = new A;
	B* pb = new B;
	void* pv = dynamic_cast<void*>(pa);
	//pv此时是指向A的对象
	void* pc = dynamic_cast<void*>(pb);
	//pc此时是指向B的对象
	return 0;
}

 

 向下转换

(1)基类指针指向的对象是派生类类型,这种可以转换成功;

(2)基类指针指向的是基类类型,这种会转换失败,返回结果0。

class B { virtual void f() {} };
class D : public B { virtual void f() {} };
int main() {
	B* pb = new D;   // unclear but ok
	B* pb2 = new B;
	D* pd = dynamic_cast<D*>(pb);   // ok: pb实际指向D
	D* pd2 = dynamic_cast<D*>(pb2); //失败,返回0
	return 0;
}

 

横向转换

还没看明白啥意思

struct V {
	virtual void f() {}  // 必须是多态的才能使用运行时检查的dynamic_cast
};
struct A : virtual V {};
struct B : virtual V {
	B(V* v, A* a) {
		// 构建时候的转换 (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) { }
};
int main() {
	D* d = new D(); // the most derived object
	A* a = d; // upcast, 向上转换, 可以使用 dynamic_cast,但不必要
	D* new_d = dynamic_cast<D*>(a); // downcast,向下转换
	B* new_b = dynamic_cast<B*>(a); // sidecast,横向转换
	return 0;
}