代码改变世界

staitic_cast原理与使用

2013-07-29 10:55  Dirichlet  阅读(1847)  评论(0编辑  收藏  举报

本文以下述结构为例:

     

总结如下:

1) static_cast用于有直接或间接关系的指针或引用之间 转换。没有继承关系的指针不能用此转换,即使二者位于同一类体系中。比如,Left,Right之间不能用static_cast,编译器无法确定二指针如何移动偏移量,请考虑Left,Right还有可能位于其他类体系中。

如果Left,Right指向同一子对象,可以用安全的dynamic_cast。

2) 向上类型转换总是成功的,static_cast关键字可写可不写,也就是分别对应显示或隐式的static_cast。也可以用括号形式的C语言风格来写,pRight = (Right*)pBottom;

3) static_cast也可用于向下类型转换,但是开发人员负责向下转换的成功与否,也就是必须确定父类指针指向的是期望的子类对象,转换才是有意义的。有时static_cast用于向下类型转换会出现编译错误,比如对于典型的虚继承的菱形结构,Left, Right都虚继承自Top,Left* left = static_cast<Left*>(top1); 会有编译错误,因为Left,Right可能同时位于多个不同的类层次结构中,编译器无法静态分析出指针的偏移量,Top也没有额外的指针去获取这个偏移量。总结一下就是向下类型类型转换最好不要用static_cast,换成dynamic_cast试试。

4) static_cast效率比dynamic_cast高,请尽可能用。大部分情况下static_cast编译时就可以确定指针移动多少偏移量,但是对于虚继承要用到虚指针确定一个到虚基类的偏移量,稍微麻烦一些。

 

#include <iostream>
using namespace std;

class Left 
{
public:
    Left():x(1){}

private:
    int x;
};

class Right
{
public:
    Right():y(2){}

private:
    int y;

};

class Bottom: public Left, public Right
{
public:
    Bottom():z(3){}

private:
    int z;
};

int main()
{
    // implicit static_cast
    Bottom* pBottom = new Bottom();
    Right* pRight = pBottom;
    Left* pLeft = pBottom;
    cout<<"Bottom Address: "<<(int)(pBottom)<<endl;
    cout<<"Right Address: "<<(int)(pRight)<<endl;
    cout<<"Left Address: "<<(int)(pLeft)<<endl<<endl;

    // explicit static_cast
    pRight = static_cast<Right*>(pBottom);
    pLeft = static_cast<Left*>(pBottom);
    cout<<"Bottom Address: "<<(int)(pBottom)<<endl;
    cout<<"Right Address: "<<(int)(pRight)<<endl;
    cout<<"Left Address: "<<(int)(pLeft)<<endl<<endl;

    // another style
    pRight = (Right*)pBottom;
    pLeft = (Left*)pBottom;
    cout<<"Bottom Address: "<<(int)(pBottom)<<endl;
    cout<<"Right Address: "<<(int)(pRight)<<endl;
    cout<<"Left Address: "<<(int)(pLeft)<<endl<<endl;

    // down cast, dev is responsible for the casting
    pRight = static_cast<Right*>(pBottom);
    pLeft = static_cast<Left*>(pBottom);

    Bottom* pBottom1 = static_cast<Bottom*>(pRight);
    Bottom* pBottom2 = static_cast<Bottom*>(pLeft);
    cout<<"Bottom Address: "<<(int)(pBottom1)<<endl;
    cout<<"Bottom Address: "<<(int)(pBottom2)<<endl<<endl;

    pBottom1 = (Bottom*)(pRight); //啥意思?需要再仔细实验。
    pBottom2 = (Bottom*)(pLeft);
    cout<<"Bottom Address: "<<(int)(pBottom1)<<endl;
    cout<<"Bottom Address: "<<(int)(pBottom2)<<endl<<endl;

    //
    // pLeft = static_cast<Left*>(pRight); // can't pass compiling, use the method below.
    pLeft = static_cast<Left*>(static_cast<Bottom*>(pRight));

}