Wednesday, October 20, 2010

类型转换-基类和派生类之间的转换

    对于内置类型,类型之间的转换比较明显,而且接触得比较多,但是对于自定义类型,尤其是基类和派生类之间到底可以有哪些转换我还是比较模糊,翻了翻书,同时自己试了试,总结如下(如有不对地方,欢迎支持):
    1.子类转成父类
using namespace std;
class A {
    public:
        void display()
        {
            cout << "in A" << endl;
        }
};

class B : public A {
    public:
        void display()
        { 
            cout << "in B" << endl;
        }
};

int main(int argc, char *argv[])

    A a;
    a.display();// A
    B b;
    //a = b; 隐式转换
    //两种旧的强制转换
    //a = A(b); function-style cast
    //a = (A)b; c-style cast
    //推荐
    b.display(); //B
    a = static_cast<A>(b);
    a.display();          // A         
}
当然转了的时候,b就转成了a

2. 父类转子类
假如参考上面的做法,将a转换给b的话,4种方法都是不可行的,那么父类在什么情况下可以转成子类呢?
参考了c++ primer的dynamic_cast操作符的解释:
可以使用dynamic_cast操作符将基类类型对象的引用或指针转换为同一层次中其他类型的引用或者指针。与dynamic_cast一起使用的指针必须是邮箱的--为0或者指向一个对象。
注意:dynamic_cast涉及运行时类型检查,如果绑定到引用或者指针的对象不是目标对象,则dynamic_cast失败的(我认为本质上指针指向的实际对象还是和目标同类型,只是指针是基类而已)。如果转换到指针类型的dynamic_cast失败,则dynamic_cast的结果为0;如果转换到引用类型的dynamic_cast失败,则抛出一个bad_cast类型的异常。
同时,需要基类至少带有一个虚函数,(这点我认为是因为运行时类型检查,类似多态) 

例子:
2.1 目标类型和运行时类型不一致,dynamic_cast的结果为0
class A {
    public:
    virtual void test()
    {
        cout << "A" << endl;
    }
};

class B : public A {
    public:
    void test()
    {
        cout << "B" << endl;
    }
};

int main(int argc, char *argv[])
{
    A *a = new A();
    B *b = dynamic_cast<B*>(a); // can't
    a->test();
    if (b != NULL ) {
        b->test();
    }
}
output:
A
2.2 没有虚函数:error
class A {
    public:
    void test()       
    {
        cout << "A" << endl;
    }
};

class B : public A {
    public:
    void test()
    {
        cout << "B" << endl;
    }
};

int main(int argc, char *argv[])
{
    A *a = new B();
    B *b = dynamic_cast<B*>(a); // 没有虚函数can't
    a->test();
    if (b != NULL ) {
        b->test();
    }
}
compiler error:cannot dynamic_cast ‘a’ (of type ‘class A*’) to type ‘class B*’ (source type is not polymorphic)  

假如目标类型和运行时类型一致,且基类含虚函数的话,即可以
如   
class A {
    public:
    virtual void test()
    {
        cout << "A" << endl;
    }
};

class B : public A {
    public:
    void test()
    {
        cout << "B" << endl;
    }
};

int main(int argc, char *argv[])
{
    A *a = new B();
    B *b = dynamic_cast<B*>(a); // can't
    a->test();
    if (b != NULL ) {
        b->test();
    }
}
                                                
output:   
B
B                                  
    

No comments:

Post a Comment