【问题标题】:C++ Inheritance Overriding Vector Member VariableC++ 继承覆盖向量成员变量
【发布时间】:2020-08-18 02:14:50
【问题描述】:

假设你有一堂课

class Foo
{
  // stuff
};

你有那个类的派生版本

class Bar : public Foo
{
  // extra stuff
};

你有一个类,其中包含指向Foos 的指针向量。

class FooManager
{
public:
  std::vector<Foo*> objects;
}

您能否将FooManager 派生为BarManager,其中BarManager 有一个指向Bar 的指针向量?

如果你做了类似的事情

class BarManager : public FooManager
{
  std::vector<Bar*> objects;
}

然后BarManager 将只是隐藏FooManager 的对象,我不想要那个额外的成员。我可以将Bar 指针推入FooManager 的对象中,这样就可以了,但是如果我想使用extra stuffBar 对象,我需要转换所有Foo*s进入Bar*s 然后如果我不小心将Foo 指针推入对象中就会出现问题。

有没有更好的解决方案?

编辑: 我正在尝试不同的方法来组织游戏的课程。所有对象都从具有纯虚拟 Update() 和 Draw() 方法的 GameObject 派生。所有对象都属于该对象类型的管理器,然后所有这些管理器都属于一个“管理器管理器”,该管理器将为管理器调用 Update() 和 Draw() 方法,这些管理器依次调用 Update() 和 Draw()对象的方法。

【问题讨论】:

  • 不,你不能那样做。 C++ 不能以这种方式工作。此外,仅仅因为BarFoo 的子类并不意味着std::vector&lt;Bar*&gt;std::vector&lt;Foo*&gt; 的子类。 C++ 模板不能以这种方式工作。这两个向量是完全不同的类型,彼此之间没有任何关系。
  • 所以我唯一的选择是在BarManager 中声明objects 并隐藏FooManagerobjects?
  • 不,FooManager 的向量可以很好地存储指向Bars 的指针。而且您不需要“将所有 Foos 转换为 Bars”,因为这正是虚拟方法的用途。虚拟继承是专为此用例设计的 C++ 强大的基础部分之一。你的 C++ 书应该有很多关于如何定义和实现虚方法的例子。
  • 我需要在Foo 有一个名为a 的成员和Bar 有一个名为b 的成员的情况下进行转换(这就是我所说的额外内容),并且我想从BarManager 访问b。任何人,您可以将评论变成答案,以便我接受。
  • XY 问题。为什么需要它?

标签: c++ inheritance vector


【解决方案1】:

不,这是不可能的。

正如一位用户指出的那样,它看起来像是一个 XY 问题。你应该更好地解释你想要达到的目标。

仅给出几个解释...

一种解决方案是在FooManagerBarManager 中使用std::vector&lt;Foo*&gt; objects; 来获得采用objects 并将objects 中的指针转换为Bar* 的函数。

class BarManager : public FooManager {
    Bar* get_at_index(std::size_t i) const { return static_cast<Bar*>(objects[i]); }
}

另一种方法是使用模板类,然后使用Manager&lt;Foo&gt; mgr;Manager&lt;Bar&gt; mgr;

template <class T>
class Manager
{
public:
  std::vector<T*> objects;
}

【讨论】:

  • 我相信 C++ 20 中的新概念和约束以及模板是我正在寻找的。​​span>
【解决方案2】:

这样做不仅不可能,而且毫无意义。想象一下如果你能做到这一点会发生什么。如果允许这样的事情:

class BarManager : public FooManager
{
  override std::vector<Bar*> objects;  // replace the base class member with this
}

那么如果你定义了另一个 Foo 的子类:

class Baz : public Foo {  // whatever

您可以将BarManagar * 转换为FooManager *

FooManager *ptr = &SomeBarManager;

然后将 Baz 插入它的数据

ptr->objects->push_back(new Baz());

当有人试图稍后访问它时,会导致可预见的混乱,就像它是酒吧一样。

所以真正的问题是为什么你想尝试做这样的事情?因为它真的没有任何意义,如果你认为它有任何意义,那么你的设计中可能存在根本不一致的地方。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多