gpt4 book ai didi

c++ - 虚函数+带基类指针的STL容器

转载 作者:行者123 更新时间:2023-11-30 01:23:38 25 4
gpt4 key购买 nike

我有一个名为 Base 的基类,它定义了一个虚函数。 Derived 类现在继承自它并实现/覆盖该虚函数。以下代码工作正常:

Base* pB = new Derived();
pB->virtual_function(); // function of class Derived gets called -> good

我的问题是,我现在将所有派生实例存储在一个 STL 容器中 std::map<ID, Base*> .这似乎会导致问题,因为当我稍后迭代该容器并尝试让每个 Base* 调用我的虚函数时,运行时仅将指针识别为 Base* 类型并且不会调用 Derived 类中的重写实现。

有没有办法让它按预期工作,还是我错过了关键点?

编辑 1: 请求了一些额外的代码,所以我们开始:

std::map<ComponentType, Base*> m_Components;
// The factory instantiates a Derived* (via functors) and returns it as Base*
Base* pB = m_pComponentFactory->createComponent(this, type);
// Lazy insert (since there is no map entry with key 'type' at that stage)
m_Components[type] = pB;

[...]

Base* pB;
for(ComponentMap::const_iterator it = m_Components.begin(); it != m_Components.end( ); ++it)
{
pB = it->second;
pB->virtual_function(); // goes to Base instead of Derived
}

编辑 2: 我刚刚意识到的一件事是我不调用 dynamic_cast (或类似的东西)在通过仿函数创建 Derived 实例之后(但我不知道将它转换成什么,因为它都是通用的/动态的)。它只是一个 return creator()创造者是仿函数。是这个问题吗?

创建者类型(函数类型)的定义:

typedef Base*(*ComponentCreator)([some params]);

编辑 3:例如,实际的仿函数是这样定义的(Renderable 和 Location 是从 Base 派生的类):

&Renderable::Create<Renderable> // or
&Location::Create<Location>

Create() 方法是 Base 类中的模板函数。

template<typename T> 
static Component* Create([some params])
{
return new T([some params]);
}

编辑 4:问题似乎是我的 clone() + CopyConstructor 处理。我的克隆目前看起来像这样:

Base* Base::clone() const
{
return new Base(*this);
}

因为我只创建了一个Base*,所以后面的虚拟分辨率无法工作。不过,我现在剩下的问题是,我不知道如何更改克隆。如 EDIT 1 所示,我有我的 m_Components映射与 Base* 指针。我现在需要克隆它们,但我只知道它们是 Base* 而不是哪个精确派生的。想到的一个想法可能是将用于创建 Derived 实例的仿函数存储在类中的第一个位置,以便稍后重用它。所以我的克隆看起来像这样:

Base* Component::clone() const
{
return m_pCreationFunctor([some params]);
}

有人看到更好的方法吗?

最佳答案

您是切片的受害者。当您复制构造一个 Base 时,您将丢失该对象的 Derived 部分。参见 http://en.wikipedia.org/wiki/Object_slicing了解更多细节。如果基类不应该被实例化,您可以考虑将其抽象化以防止将来犯这种错误。

这种情况下的修复可能是有一个虚拟的 Base * clone() 方法并在派生类中覆盖它。

class Base{
...
virtual Base * clone() const = 0;
...
};

class Derived : public Base {
...
Base * clone() const override { return new Derived(*this); }
...
};

如果你真的想避免重写克隆方法,你可以使用一个中间体 CRTP类即

struct Base{
virtual Base * clone() = 0;
};

template <typename D>
struct B : public Base {
virtual Base * clone() { return new D(*static_cast<D*>(this)); }
};

struct D : public B<D>{};

关于c++ - 虚函数+带基类指针的STL容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14672394/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com