从基指针容器中访问派生成员

时间:2014-08-14 11:11:18

标签: c++ casting polymorphism containers

请考虑以下代码:

struct Object
{
bool hasComponent(std::string sComponentID);
Component& getComponent(std::string sComponentID);
std::vector<Component*> vComponents;
}

struct System
{
std::vector<Object*> vObjects;
}

我的系统将迭代其向量中的每个Object,并需要从Component的派生成员访问数据(它们都包含系统要使用的不同状态和数据)。 我考虑过这样的事情:

struct NetworkComponent : Component
{
std::string sID;
NetworkComponent(std::string tempID) : sID(tempID) {};

//Network data here
}

for(Object* p : vObjects)
{
     if(p->hasComponent("network")
     {
     NetworkComponent& network = static_cast<NetworkComponent&>(p->getComponent("network");
     //Access the data in the structure and do stuff with it.
     }
}
然而,这确实感觉非常“hacky”;更不用说不安全了。 我想知道是否有更好的方法来做这样的事情,或者至少如何在将来避免这个问题?

有没有关于这个主题的好文章我可以查阅? 编辑:dynamic_cast不是一个选项,因为它有多慢。

3 个答案:

答案 0 :(得分:1)

听起来你正试图重新发明dynamic_cast

答案 1 :(得分:0)

我重构getComponent方法以返回指针(如果不存在这样的组件,则为nullptr)而不是引用,并且还使用常量引用传递字符串参数:

Component * getComponent(const std::string & sComponentId);

然后你可以这样做:

template <typename CompType, typename ... Args>
CompType * getComponentOfType(Args && ... args)
{ return dynamic_cast<CompType *>(getComponent(std::forward<Args>(args)...)); }

如果dynamic_cast不是此处的选项,请使用static_cast。通过这样做,在这种情况下,您只会失去编程错误的安全层。

做类似的事情:

for(Object * const p : vObjects) {
    assert(p);
    NetworkComponent * const net =
            p->getComponentOfType<NetworkComponent>("network");
    if (net) {
        // Use the network component.
    }
}

答案 2 :(得分:0)

您可以定义class Object以包含要在派生类中使用的虚拟方法
他们每个人都应该抛出异常,这意味着这个对象没有重新定义这个方法 当然,在每个派生类中,您应该重新定义它的对象应该具有的方法。