C++ - 向上抛射和向下投射



在我的例子中:

在上投时,第二个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;
}

向上投射隐含在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

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

向下铸造不太有用,应尽可能避免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
}

此链接提供了对该主题非常有用的介绍。

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

在您的情况下,由于您使用的是C++,因此您应该依靠更安全的铸造机制。因此,您应该使用 dynamic_cast<Derived*>(b) 而不是 (Derived*)b 。这使您可以确保您实际上拥有指向基类(接口)的对象的指针,该指针是通过强制转换类型为 Derived 的对象获得的。本页提供了进一步的说明。

如果你想称打印为"Base",你应该这样做;在这里,我们将派生类对象向上转换为此基类对象,所以,当我们调用 pBase->print() 时,它会转到基类并调用它;但是,如果print函数是虚拟的,它将调用派生类,因为它在派生类中重写了此函数。

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

最新更新