通常,在C++中需要用到各种类型转换,典型的如const_cast, dynamic_cast, reinterpret_cast, static_cast。
这时讲两种实现办法: dynamic_cast和直接计算的办法
(1) dynamic_cast
最常用的,dynamic_cast: 动态类型转换,可以在父类与子类之间进行安全的类型转换,运行时类型检查,并且可以知道自己子类的类型。缺点是耗时稍微有点长。
reinterpret_cast: 强制类型转换,可以在不同类型之间进行强制转换,很难保证移植性。速度快。
这里不打算对各个类型转换进行详细解释,相关文档网络上相当多。这 里只重点讲一下dynamic_cast。
dynamic_cast最大的好处是可以用来进行“安全向下转换”。
假设有类A、B和C,如下,
class A {
};
class B : public class A {
};
class C : public class B {
};
A* pc = new C;
当我们将父类指针指向一个new出来的子类B或C对象时,那么可以使用dynamic_cast将该指针类型安全转换为C或B。
我们来运行一下下面的例子,重点是注意最后那个指针p_grand,
using namespace std;
template<typename Base, typename T>
inline bool instanceof(const T* ptr) {
return dynamic_cast<const Base*>(ptr) != nullptr;
}
class GrandParent {
public:
GrandParent() {}
virtual void test() = 0;
};
class Parent : public GrandParent
{
public:
virtual ~Parent() {}
virtual void test() { std::cout << "Parent\n"; }
};
class Child : public Parent {
public:
virtual void test() { std::cout << "Child\n"; }
};
class Someclass {
public:
Someclass(){}
virtual void test() { std::cout << "Someclass\n"; }
};
int main() {
Parent p;
Child c;
Someclass sc;
Parent* p_parent = &p;
Child* p_child = &c;
Someclass* p_some = ≻
GrandParent* p_grand = &c;
if (instanceof<GrandParent>(p_parent)) {
cout << "p_parent is instance of GrandParent" << endl;
}
else {
cout << "p_parent is NOT instance of GrandParent" << endl;
}
if (instanceof<Parent>(p_parent)) {
cout << "p_parent is instance of Parent" << endl;
}
else {
cout << "p_parent is NOT instance of Parent" << endl;
}
if (instanceof<Child>(p_parent)) {
cout << "p_parent is instance of Child" << endl;
}
else {
cout << "p_parent is NOT instance of Child" << endl;
}
if (instanceof<Someclass>(p_parent)) {
cout << "p_parent is instance of Someclass" << endl;
}
else {
cout << "p_parent is NOT instance of Someclass" << endl;
}
cout << "----------------------------------------------------" << endl;
if (instanceof<GrandParent>(p_child)) {
cout << "p_child is instance of GrandParent" << endl;
}
else {
cout << "p_child is NOT instance of GrandParent" << endl;
}
if (instanceof<Parent>(p_child)) {
cout << "p_child is instance of Parent" << endl;
}
else {
cout << "p_child is NOT instance of Parent" << endl;
}
if (instanceof<Child>(p_child)) {
cout << "p_child is instance of Child" << endl;
}
else {
cout << "p_child is NOT instance of Child" << endl;
}
if (instanceof<Someclass>(p_child)) {
cout << "p_child is instance of Someclass" << endl;
}
else {
cout << "p_child is NOT instance of Someclass" << endl;
}
cout << "----------------------------------------------------" << endl;
if (instanceof<GrandParent>(p_some)) {
cout << "p_some is instance of GrandParent" << endl;
}
else {
cout << "p_some is NOT instance of GrandParent" << endl;
}
if (instanceof<Parent>(p_some)) {
cout << "p_some is instance of Parent" << endl;
}
else {
cout << "p_some is NOT instance of Parent" << endl;
}
if (instanceof<Child>(p_some)) {
cout << "p_some is instance of Child" << endl;
}
if (instanceof<Someclass>(p_some)) {
cout << "p_some is instance of Someclass" << endl;
}
else {
cout << "p_some is NOT instance of Someclass" << endl;
}
cout << "----------------------------------------------------" << endl;
if (instanceof<GrandParent>(p_grand)) {
cout << "p_grand is instance of GrandParent" << endl;
}
else {
cout << "p_grand is NOT instance of GrandParent" << endl;
}
if (instanceof<Parent>(p_grand)) {
cout << "p_grand is instance of Parent" << endl;
}
else {
cout << "p_grand is NOT instance of Parent" << endl;
}
if (instanceof<Child>(p_grand)) {
cout << "p_grand is instance of Child" << endl;
}
else {
cout << "p_grand is NOT instance of Child" << endl;
}
if (instanceof<Someclass>(p_grand)) {
cout << "p_grand is instance of Someclass" << endl;
}
else {
cout << "p_grand is NOT instance of Someclass" << endl;
}
}
该例子的输出结果如下,
输出结果:
p_parent is instance of GrandParent
p_parent is instance of Parent
p_parent is NOT instance of Child
p_parent is NOT instance of Someclass
----------------------------------------------------
p_child is instance of GrandParent
p_child is instance of Parent
p_child is instance of Child
p_child is NOT instance of Someclass
----------------------------------------------------
p_some is NOT instance of GrandParent
p_some is NOT instance of Parent
p_some is instance of Someclass
----------------------------------------------------
p_grand is instance of GrandParent
p_grand is instance of Parent
p_grand is instance of Child
p_grand is NOT instance of Someclass
(2) 直接计算的办法
这个办法的特点就是没有类型匹配计算,使用时速度非常快。
这里只是提一下,这种只能针对父类为非虚类时,例如对前面p_grand,因为父类GrandParent是纯虚类,所以不适合,但假设其不是纯虚类,就可以进行正确的计算,
template<typename Derived, typename Base>
inline int CalcBaseOffset() {
const static int s_off = (reinterpret_cast<char*>(static_cast<Base*>(reinterpret_cast<Derived*>(0x10000000))) - reinterpret_cast<char*>(0x10000000));
return s_off;
};
我们用下面的源码测试一下,
class A {
public:
A() {}
void test() {
cout << "A" << " a= " << a << " b= " << b << " c= " << c << endl;
}
int a = 1;
int b = 2;
double c = 3;
};
class B {
public:
B() {}
void test() {
cout << "B" << endl;
}
};
class C {
public:
C() {}
void test() {
cout << "C" << endl;
}
};
class AB : public A, public B {
public:
AB() {}
void test() {
cout << "AB" << endl;
}
};
class AC : public A, public C {
public:
AC() {}
void test() {
cout << "AC" << endl;
}
};
int main() {
int baseOffset1 = CalcBaseOffset<AB, B>();
int baseOffset2 = CalcBaseOffset<AC, C>();
assert(baseOffset1 == baseOffset2);
AB* p1 = new AB;
AC* p2 = new AC;
p1->test();
p2->test();
B* pB = p1; //c++ 编译器会正确处理
C* pC = p2;
pB->test();
pC->test();
long long lv = (long long)pB;
A* pA1 = (A*)(lv - baseOffset1);
assert(pA1 == p1);
cout << pA1 << " == " << p1 << endl;
lv = (long long)pC;
A* pA2 = (A*)(lv - baseOffset2);
assert(pA2 == p2);
cout << pA2 << " == " << p2 << endl;
pA1->test();
pA2->test();
return 0;
}
输出结果:
AB
AC
B
C
00B28AF0 == 00B28AF0
00B285A8 == 00B285A8
A a= 1 b= 2 c= 3
A a= 1 b= 2 c= 3
本文结束。