类模板中的虚函数

时间:2015-08-09 20:33:51

标签: c++ templates

我有一个名为Cache的模板类,它是字符串和对象的std :: map的持有者。

template<class T>
class Cache
{
public:
    Cache() {}
    virtual ~Cache();

    virtual T* loadObject(const char *file);
    virtual bool removeObject(const char *file);
    virtual void removeAllObjects();

    virtual unsigned int getNumObjects() const;
    virtual T* getObject(const char *file);

protected:
    typedef std::shared_ptr<T> t_ptr;

    std::unordered_map<std::string, t_ptr> _objects; //file, shared ptr of object
};

template<class T>
T* Cache<T>::loadObject(const char *file)
{
    //if object exists
    T *obj = getObject(file);
    if(obj)
        return obj;

    obj = new T();

    if(obj)
        return _objects.insert(std::make_pair(file,t_ptr(obj))).first->second.get();
    else
        return nullptr;
}

并且从Cache继承的模板类称为ResourceCalled,它基本上是同一个类但使用不同的loadObject()方法。

template<class T>
class ResourceCache : public Cache<T>
{
public:
    ResourceCache(ResourceLoader<T> *resourceLoader) : _resourceLoader(resourceLoader)
    {}

    virtual T* loadObject(const char *file);

private:
    ResourceLoader<T> *_resourceLoader;
};

template<class T>
T* ResourceCache<T>::loadObject(const char *file)
{
    //if object exists
    T *obj = getObject(file);
    if(obj)
        return obj;

    obj = _resourceLoader->load(file);
    if(obj)
        return _objects.insert(std::make_pair(file,t_ptr(obj))).first->second.get();
    else
        return nullptr;
}

在我的程序中,我启动了ResourceCache&lt;&gt;将T设置为一个名为Mesh的类,在其构造函数中有一个参数。现在,当我尝试编译程序时,编译器会抱怨:

  

错误C2512:&#39;网格&#39; :没有合适的默认构造函数

它试图为Cache而不是ResourceCache构建代码。但是当我在Cache :: loadObject()之前省略virtual关键字时,程序会编译。

为什么会这样?我学会了在继承时总是使用virtual关键字。

2 个答案:

答案 0 :(得分:2)

Cache<T>::loadObject()中,您有

obj = new T();

如果您的案例中TMesh没有默认构造函数,那么该行不起作用。

Cache<T>::loadObject()virtual时,实例化基类实现以及函数的派生类实现。

Cache<T>::loadObject()不是virtual时,只实例化该函数的派生类实现。只有明确使用该函数的基类实现才会被实例化。

答案 1 :(得分:1)

是的,它正在尝试构建Cache,因为这是你告诉编译器在某一点上做的事情:

O(nlog(n))

目前,其中T是一个实际的类型的点,编译器需要实例缓存,以及包括所述方法缓存::装入对象,如果T不具有默认的构造不编译。

您可以使基类的loadObject为纯虚拟,然后从抽象类派生一个额外的类,该抽象类实现您设置为默认值的旧loadObject方法。