【问题标题】:Calling an overridden function from a list of its base class?从其基类列表中调用重写函数?
【发布时间】:2012-12-17 00:43:54
【问题描述】:

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

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 的列表.

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

【问题讨论】:

  • 继承不是这样工作的。也许一本关于 C++ 的基本教科书会花时间花时间?

标签: c++ inheritance virtual overriding


【解决方案1】:

您需要使用Base* 的列表(即指向基址的指针),或者最好使用std::unique_ptr&lt;Base&gt;std::shared_ptr&lt;Base&gt;

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

【讨论】:

  • “[派生类] 的大小可以与 [与其基类] 相同,具体取决于基类是否为空”——派生类 类是否为空指示 sizeof(Base) 是否可以等于 sizeof(Derived)
  • @TonyD 确实,精神失常。更新了我的答案。
【解决方案2】:

获取每个基类的指针,然后将其向下转换为派生类。之所以称为向下转换,是因为在 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
} 

【讨论】:

  • 来自问题 - “我可以将其设为 Derived 而不是 Base 的列表,这将解决它,但我将调用这些继承的类各种不同的东西,所以我需要基地列表。”。显然,您不能假设所有容器元素都是特定的Derived 类型。
猜你喜欢
  • 2011-05-03
  • 2011-06-17
  • 2023-01-04
  • 1970-01-01
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多