C ++ - 向上转换和向下转换

时间:2016-01-30 12:59:37

标签: c++ class inheritance downcast upcasting

在我的例子中:

在向上转发时,第二个d.print()来电不应该打印“基地”吗?

是不是“d”派生对象上传到基类对象?

在向下看,它有什么优势?

你能以实际的方式解释上传和下传吗?

#include <iostream>
using namespace std;

class Base {
public:
    void print() { cout << "base" << endl; }
};

class Derived :public Base{
public:
    void print() { cout << "derived" << endl; }

};

void main()
{
    // Upcasting
    Base *pBase;
    Derived d;
    d.print();
    pBase = &d;
    d.print();

    // Downcasting
    Derived *pDerived;
    Base *b;
    pDerived = (Derived*)b;
}

2 个答案:

答案 0 :(得分:8)

向上转换在C ++中是隐含的,在处理虚拟调度时会被大量使用。换句话说,您有一个指向Base的指针,您可以从该指针访问整个类层次结构的公共接口,并且可以在运行时完成选择。这假定您的接口函数标记为virtual。例如:

Base* pBase; 
cin >> x; 
if(x == 0) // this is done at runtime, as we don't know x at compile time
    pBase = new Derived1;
else
    pBase = new Derived2;

pBase->draw(); // draw is a virtual member function

在运行时完成调度的这些情况下,它非常有用。简单地说,upcasting允许将派生类视为基类(通过其通用接口)。

向下投射不太有用,只要可以,就应该避免使用IMO。一般来说,这是设计糟糕的标志,因为很少需要将Base对象转换为派生对象。可以通过dynamic_cast完成(并检查结果),例如

Base* pBase = new Derived; // OK, the dynamic type of pBase is Derived
Derived* pDerived = dynamic_cast<Derived*>(pBase);
if(pDerived) // always test  
{
    // success
}
else
{
    // fail to down-cast
}

This link为该主题提供了非常有用的介绍。

答案 1 :(得分:2)

您需要使用虚拟方法才能启用RTTI

在您的情况下,由于您使用的是C ++,因此您应该依赖更安全的转换机制。因此,您应该使用(Derived*)b而不是dynamic_cast<Derived*>(b)。这允许您确保实际上拥有指向通过强制转换Derived类型的对象获得的基类(接口)的对象的指针。 This page提供了进一步的解释。