我有一个名为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关键字。
答案 0 :(得分:2)
在Cache<T>::loadObject()
中,您有
obj = new T();
如果您的案例中T
,Mesh
没有默认构造函数,那么该行不起作用。
当Cache<T>::loadObject()
为virtual
时,实例化基类实现以及函数的派生类实现。
当Cache<T>::loadObject()
不是virtual
时,只实例化该函数的派生类实现。只有明确使用该函数的基类实现才会被实例化。
答案 1 :(得分:1)
是的,它正在尝试构建Cache,因为这是你告诉编译器在某一点上做的事情:
O(nlog(n))
目前,其中T是一个实际的类型的点,编译器需要实例缓存,以及包括所述方法缓存::装入对象,如果T不具有默认的构造不编译。
您可以使基类的loadObject为纯虚拟,然后从抽象类派生一个额外的类,该抽象类实现您设置为默认值的旧loadObject方法。