static_cast和dynamic_cast总结
class A {}
class B {}
注意: 若继承 A为基类 B为派生类
代码 | class A { }; class B:public A { }; | class A { public: virtual void Test(){} virtual ~A(){} }; class B:public A { public: //virtual void Test(){} //virtual ~B(){} }; | class A { public: virtual void Test(){} virtual ~A(){} }; class B:public A { public: virtual void Test(){} virtual ~B(){} }; |
---|---|---|---|
继承关系 | 有继承关系 父无虚函数 | 有继承关系 父有虚函数 子无 | 有继承关系 父子有虚函数 |
static_cast | //right 基类指针指向子类 pObjA = static_cast<A*>(pObjB); //right强制转换 OK 基类到子类 pObjB = static_cast<B*>(pObjA); 均不为NULL //转换为基类引用 objA = static_cast<A&>(objB); objA = static_cast(objB); //right 基类指针指向子类对象 pObjA = pObjB; //right 基类指向子类 objA = objB; //right 转换为基类引用 objB = static_cast<B&>(objA); //error 基类不可转换为子类 //objB = static_cast (objA); //error 子类指针指向父类对象 //pObjB = pObjA; //error 无赋值操作符 //objB = objA; | //right 基类指针指向子类 pObjA = static_cast<A*>(pObjB); //强制转换 OK 基类到子类 pObjB = static_cast<B*>(pObjA); 均不为NULL //强制转换 OK 基类到子类 pObjA = &objB; pObjB = static_cast<B*>(pObjA); if (pObjB) { cout << “B Succ” << endl; } else { cout << “B NULL” << endl; } | //right 基类指针指向子类 pObjA = static_cast<A*>(pObjB); //强制转换 OK 基类到子类 pObjB = static_cast<B*>(pObjA); 均不为NULL //强制转换 OK 基类到子类 pObjA = &objB; pObjB = static_cast<B*>(pObjA); if (pObjB) { cout << “B Succ” << endl; } else { cout << “B NULL” << endl; } |
dynamic_cast | //right 基类指针指向子类 pObjA = dynamic_cast<A*>(pObjB); 且pObjA不为NULL // ERROR 继承关系 父类无虚函无多态 pObjB = dynamic_cast<B*>(pObjA); | //right 基类指针指向子类 //上行一般没问题 pObjA = dynamic_cast<A*>(pObjB); // warning 继承关系 pObjB = dynamic_cast<B*>(pObjA); pObjB = NULL //下行转换成功事例 pObjA = &objB; pObjB = dynamic_cast<B*>(pObjA); pObjB SUCCSESS | //right 基类指针指向子类 //上行一般没问题 pObjA = dynamic_cast<A*>(pObjB); // warning 继承关系 pObjB = dynamic_cast<B*>(pObjA); pObjB = NULL //下行转换成功事例 pObjA = &objB; pObjB = dynamic_cast<B*>(pObjA); pObjB SUCCSESS |
向上转换,即为子类指针指向父类指针(一般不会出问题);A = dynamic_cast(B)
向下转换,即将父类指针转化子类指针。B = dynamic_cast(A) (不报错,编译通过,但是转换失败NULL)
向下转换的成功与否还与将要转换的类型有关,即要转换的指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败。
代码 | class A { public: virtual void Test(){} virtual ~A(){} }; class D { }; | class A { }; class D { }; |
---|---|---|
继承关系 | 无继承关系 有多态 | 无继承关系 无多态 |
static_cast | // ERROR pObjD = static_cast<D*>(pObjA); // ERROR pObjA = static_cast<A*>(pObjD); | // ERROR pObjD = static_cast<D*>(pObjA); // ERROR pObjA = static_cast<A*>(pObjD); |
dynamic_cast | //warning pObjD = dynamic_cast<D*>(pObjA); cout << “D NULL” << endl; | // ERROR pObjD = dynamic_cast<D*>(pObjA)); |
static_cast
- 有继承都 ok 但是 B=static_cast(A) 不安全
- 无继承 一般不 ok 若想成功
只可对象转换
class A
{
public:
virtual void test(){}
virtual ~A(){}
};
class D
{
public:
D(){}
D(A& a){}
//virtual ~D(){}
};
A objA;
D objD;
objD = static_cast<D>(objA);
如果让非继承关系通过编译,那么D类必须含有以A类的对象(或对象的引用)为参数的构造函数
dynamic_cast
- 编译 通过 必须有多态 有虚函数 可以没有继承 但存在 NULL
- 转换成功,必须多态,继承,
基类指向子类 ok (子类转换为基类 ok ) A = dynamic_cast(B)
子类指向基类 要 ok (基类转换为子类 ok ) B = dynamic_cast(A) 必须 基类引用或者指向子类 否则 NULL,成功实例如下
dynamic_cast 下行转换
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Base{
public:
Base() :str(nullptr){}
Base(string s) :str(s){}
virtual void print()
{
cout << str << " ";
}
private:
string str;
};
class Derived:public Base
{
public:
Derived(){}
Derived(string s,int i) :Base(s),ival(i){}
void print()
{
Base::print();
cout << ival << endl;
}
void print_ival()
{
cout << "ival:" << ival << endl;
}
private:
int ival;
};
int main()
{
Base base("aaa");
Derived de("xxx", 111);
//指针dynamic_cast
Base* pb = &de;
if (Derived* pd1 = dynamic_cast<Derived*>(pb))
{
pd1->print_ival();
}
else
{
//转换失败返回空指针
cout << "type error..." << endl;
}
//引用dynamic_cast
Base& rf = de;
try
{
Derived& d = dynamic_cast<Derived&>(rf);
d.print_ival();
}
catch (const std::bad_cast& ex)
{
//转换失败,抛出std::bad_cast异常
cout << ex.what();
}
// system("pause");
}
完整测试代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class A
{
public:
virtual void foo(){}
};
class B
{
public:
virtual void foo(){}
};
class C : public A, public B
{
public:
virtual void foo(){}
};
class D {};
class E : public D {};
class F : public D {};
class G {};
void bar1(A *pa)
{
if (B *pb = dynamic_cast<B *>(pa))//无继承关系 但是存在多态//为空
{
cout << "bar1 pb succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar1 pb error..." << endl;
}
B* pb=new B();
if (A *pa1 = dynamic_cast<A *>(pb))//无继承关系 但是存在多态//为空
{
cout << "bar1 pa1 succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar1 pa1 error..." << endl;
}
delete pb;
// B *pb = static_cast<B *>(pa); //error A B不存在继承关系
if (C *pc = static_cast<C *>(pa))
{
cout << "bar1 pc succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar1 pc error..." << endl;
}
//C *pc = static_cast<C *>(pa); //ok
// C *pc1 = static_cast<C *>(pb); //ok
}
void bar1_2(A *pa,C *pc)
{
if (A *pa1 = static_cast<A *>(pc))
{
cout << "bar1_2 pa1 succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar1_2 pa1 error..." << endl;
}
if (C *pc1 = static_cast<C *>(pa))//ok //No safe
{
cout << "bar1_2 pc1 succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar1_2 pc1 error..." << endl;
}
// C *pc1 = static_cast<C *>(pa); //ok //No safe
if (C *pc2 = dynamic_cast<C *>(pa))
{
cout << "bar1_2 pc2 succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar1_2 pc2 error..." << endl;
}
if (A *pa2 = dynamic_cast<A *>(pc))
{
cout << "bar1_2 pa2 succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar1_2 pa2 error..." << endl;
}
// A a;
// B b;
// b = static_cast<B>(a);
}
void bar2()
{
C c;
A *pa = &c;
B *pc = static_cast<B *>(static_cast<C *>(pa));//A->C转换不安全 C->B安全
if (pc)
{
cout << "bar2 pc succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar2 pc error..." << endl;
}
}
void bar3(D* pD) {
// E* pb1 = dynamic_cast<E*>(pD); //error //无多态类型//dynamic_cast不可转换
E* pE = static_cast<E*>(pD); //ok NOt safe //基类指针指向子类
if (pE)
{
cout << "bar3 pE succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar3 pE error..." << endl;
}
D* pd3= static_cast<D *>(pE); //right //基类指针指向子类
if (pd3)
{
cout << "bar3 pd3 succ..." << endl;
}
else
{
//转换失败返回空指针
cout << "bar3 pd3 error..." << endl;
}
E* pd4 = static_cast<E *>(pD); //right //强制转换 OK 基类指针到子类指针
//但是不安全 若pd4调用E有而D没有的,则访问越界
E* pE2;
// F* pF = static_cast<F*>(pE2); //error 继承于统一类的派生指针之间转换
// E* pF3 = static_cast<E*>(pF); //error 继承于统一类的派生指针之间转换
F* pF2;
// G* pG = static_cast<G*>(pF2); //error 两个无关联之间转换
}
void bar4()
{
D objd;
E obje;
G objg;
objd = static_cast<D&>(obje); //转换为基类引用
objd = static_cast<D>(obje);
// obje = static_cast<E>(objd); //error 不能进行转换 不能讲D赋值给E
// objg = static_cast<G&>(objd); //error 不能进行转换 不能讲D赋值给E
// objg = static_cast<G>(objd);
/*
所以,如果让以上代码通过编译,
那么B类必须含有以A类的对象(或对象的引用)为参数的构造函数。
如下:
B(A& a)
{
// ...
}
*/
}
int main()
{
A *pa = new A();
B *pb = new B();
bar1(pa);
C *pc = new C();
bar1_2(pa,pc);
bar2();
D *pd = new D();
bar3(pd);
bar4();
return 0;
}
[1] https://www.cnblogs.com/larry-xia/p/10325643.html
[2] https://blog.csdn.net/zhouwei1221q/article/details/44978361
[3] https://www.cnblogs.com/pigerhan/archive/2013/02/26/2933590.html
吐槽: Markdown真难用