从其基类列表中调用重写的函数

Calling an overridden function from a list of its base class?

本文关键字:重写 函数 调用 基类 列表      更新时间:2023-10-16

假设我有一个带有虚函数的空类:

class Base
{
public:
    virtual void Foo(){std::cout << "this is the base class";}
}

然后我有一个继承自Base并覆盖Foo()的类:

class Derived : public Base
{
public:
    void Foo(){std::cout << "this is the derived class";}
}

然后还有其他一些类包含Base列表:

class OtherClass
{
public:
    std::vector<Base> listOfBases; //note it's not std::list<Derived>
}

如何循环浏览listOfBases并为Derived类而不是Base类调用Foo()?现在,如果我说listOfBases[i].Foo();那么这是基类将打印的,但我希望打印Derived类中被覆盖的那个。

我可以把它做成一个Derived列表而不是Base,这会修复它,但我将把这些继承的类称为各种不同的东西,所以我需要一个Base列表。

那么如何从其基类列表中调用被覆盖的函数呢?

您需要使用Base*列表(即指向 Base 的指针),或者最好是 std::unique_ptr<Base>std::shared_ptr<Base>

这是因为对象模型和复制C++。派生类必须至少与其基类一样大(它们的大小可以相同,具体取决于派生类是否为空)。由于C++在向vector添加项目时利用复制(或可能在C++11中移动),它必须为n个Base对象分配足够的空间。由于vector几乎总是围绕简单array的包装器,试图将一个(可能大小不同)Derived对象添加到Base对象的array中是未定义的行为。

获取指向每个基类的指针,然后将其向下转换为派生类。之所以称为向下转换,是因为在 UML 图中,通常将基类绘制在派生类之上。

for ( auto q = listOfBases.begin(); q != listOfBases.end(); ++q )
{
    Base* pBase = &(*q); // Get pointer to Base class. Can't downcast on object.
    Derived* pDerived = dynamic_cast<Derived*>(pBase); // Downcast
    pDerived->Foo();   // Call Foo() of Derived
}