Phi*_*ier 1 c++ virtual inheritance overriding stl
我有一个名为Base的基类,它定义了一个虚函数.Derived类现在继承自它并实现/覆盖该虚函数.以下代码工作得很好:
Base* pB = new Derived();
pB->virtual_function(); // function of class Derived gets called -> good
Run Code Online (Sandbox Code Playgroud)
我的问题是,我现在将所有派生实例存储在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
}
Run Code Online (Sandbox Code Playgroud)
编辑2:我刚才意识到的一件事是,dynamic_cast在通过仿函数创建Derived实例之后我没有调用 (或者类似的东西)(但是我不知道该把它转换成什么,因为它都是通用的/动态的).它只是一个return creator()创造者是操纵者.这是问题吗?
创建者类型的定义(功能类型):
typedef Base*(*ComponentCreator)([some params]);
Run Code Online (Sandbox Code Playgroud)
编辑3: 实际的仿函数是这样定义的(Renderable和Location是Base的派生类):
&Renderable::Create<Renderable> // or
&Location::Create<Location>
Run Code Online (Sandbox Code Playgroud)
使用Create()方法作为类Base中的模板函数.
template<typename T>
static Component* Create([some params])
{
return new T([some params]);
}
Run Code Online (Sandbox Code Playgroud)
编辑4: 问题似乎是我的clone()+ CopyConstructor处理.我的克隆目前看起来像这样:
Base* Base::clone() const
{
return new Base(*this);
}
Run Code Online (Sandbox Code Playgroud)
由于我只创建一个Base*,以后的虚拟分辨率无法工作.我现在离开的问题是,我不知道如何更改克隆.如编辑1所示,我的m_Components地图有Base*指针.我现在需要克隆它们,但我只知道它们是Base*而不是哪个精确的衍生物.想到的一个想法可能是存储用于在类中首先创建Derived实例的函数,以便稍后重用它.所以我的克隆看起来像这样:
Base* Component::clone() const
{
return m_pCreationFunctor([some params]);
}
Run Code Online (Sandbox Code Playgroud)
有人看到更好的方法吗?
你是切片的受害者.复制构造Base时,将丢失对象的派生部分.有关详细信息,请参见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); }
...
};
Run Code Online (Sandbox Code Playgroud)
如果你真的想避免重写克隆方法,你可以使用中间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>{};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1464 次 |
| 最近记录: |