模板使用不当?

6 c++ templates

我理解模板有点被归咎于二进制膨胀,我也理解模板只是一种模式.我真的不明白那里的螺母和螺栓.

很多时候我看到代码如下,它返回一个基类指针.

class GameObject
{
public:
    Component* getComponent(std::string key);
};

static_cast<Comp>(obj.getComponent("Comp"));
Run Code Online (Sandbox Code Playgroud)

而不是使方法成为模板方法.

class GameObject
{
public:
    template<typename T>
    T* getComponent(std::string key);
};

obj.getComponent<Comp>("Comp");
Run Code Online (Sandbox Code Playgroud)

这种风格还是与模板相关的性能损失?

Kev*_*vin 3

该方法采用的“键”似乎实际上是一种类型(要返回的组件的类型),这一事实表明,直到运行时才真正知道该类型。如果是这种情况,那么像模板这样的编译时机制将不起作用。

唯一的选择是返回基类指针。通常,当使用此模式时,仅针对基类调用虚拟方法 - 因此派生类的实际类型并不重要(因此不需要 static_cast 或dynamic_cast)。

编辑:

正如 PhilCK 在评论中指出的那样,该类型实际上在编译时就已知。如果是这种情况,那么动态类型查找就不再需要,并且可以使用简单的工厂方法:

class GameObject {
    A getComponentA();
    B getComponentB();
    C getComponentC();
    // etc.
}

// which is more or less identical to:

class ComponentFactory {
    public:
    virtual Component* create() = 0;
};
class GameObject {
    std::map<std::string,ComponentFactory> m;
    public:
    GameObject() {
        // presumably a private map has to be populated with string -> factory methods here
    }

    template<class T>
    T* getComponent(const std::string& s) { 
        // either the static_cast is needed here, or an alternate (messier)
        // implementation of getComponent is needed.
        // it's still possible for the wrong type to be passed (by mistake)
        // and the compiler won't catch it (with static_cast). Since this could lead
        // to heap corruption the only safe way with this type of 
        // implementation is dynamic_cast.
        return static_cast<T>(m[s].create());
    }
};

// this doesn't even compile:
// return types:
class GameObject {
    template <class T>
    T* getComponent(const std::string& s) {
        if (s == "A") return new A();
        else if (s == "B") return new B();
        // etc..
        else throw runtime_error("bad type");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我认为有两种选择。

1)使用简单工厂方法,其中根本不需要案例模板。2)将map ->工厂方法实现与dynamic_cast一起使用(这似乎违背了使用动态类型创建的目的),并且如果不需要动态类型,实际上会变得不必要的复杂