简体   繁体   English

C ++继承:调用模板的子类函数

[英]C++ Inheritance: Calling subclass function of template

I have a templated class, and a subclass of the templated class in order to implement a function differently. 我有一个模板化类和一个模板化类的子类,以便以不同的方式实现功能。 Since I want to keep the flexibility of having multiple subclasses, I don't directly store the subclass itself. 因为我想保持拥有多个子类的灵活性,所以我不直接存储子类本身。 In Java, something like what I'm trying to do would work, but apparently it doesn't in C++. 在Java中,类似我想做的事情可以工作,但显然在C ++中却行不通。

template<class Res> class Loader {
public:
    Res* loadFromFile(std::string filePath);
};


template<class Res> inline Res* Loader<Res>::loadFromFile(std::string filePath){return NULL;}

Subclass: 子类:

class TextureLoader : public Loader<sf::Texture> {
public:
    sf::Texture* loadFromFile(std::string path);
};

inline sf::Texture* TextureLoader::loadFromFile(std::string path){
    sf::Texture* texture = new sf::Texture();
    texture->loadFromFile(path);
    return texture;
}

Somewhere in another class I store an instance of a Loader: 在另一个类的某个地方,我存储了一个Loader的实例:

Loader<Res> * loader;

My problem is, that even if I assign a TextureLoader instance to that loader variable, only the superclass-function is called, but not the actually implemented subclass function. 我的问题是,即使将TextureLoader实例分配给该加载程序变量,也仅会调用超类函数,而不会调用实际实现的子类函数。 How can I achieve to call the subclas function while keeping the flexibility of having multiple loaders? 如何在保持多个装载程序的灵活性的同时调用subclas函数?

You may not want inheritance - it looks like you may want specialization instead: 您可能不想要继承-看起来您可能想要特殊化:

template<>
sf::Texture* Loader<sf::Texture>::loadFromFile(std::string path) {...}

Now just use Loader<sf::Texture> where before you planned to use TextureLoader . 现在只需使用Loader<sf::Texture> ,然后再计划使用TextureLoader Or, typedef the latter to the former. 或者,将后者键入到前者。

In order for dynamic dispatch to take place you need to declare the member function virtual in the base class. 为了进行动态调度,您需要在基类中声明虚拟的成员函数。 You will also want to declare the destructor as virtual to ensure that derived classes are properly cleaned up when they are deleted through a base class type. 您还需要将析构函数声明为虚拟的,以确保在通过基类类型删除派生类时正确清理了派生类。

template<class Res> class Loader {
public:
    virtual ~Loader() [}
    virtual Res* loadFromFile(std::string filePath);
};

Your function is never marked as virtual. 您的功能永远不会被标记为虚拟的。 That said, you should really make it abstract, because it has no use without overwriting it: 就是说,您应该真正使它抽象化,因为不重写它就没有用:

template<class T> class Loader 
{
public:
   virtual T* LoadFromFile(const std::string& filePath) = 0;
   virtual ~Loader() {}
};

class TextureLoader : public Loader<sf::Texture>
{
public:
   virtual sf::Texture* LoadFromFile(const std::string& filePath);
   {
     sf::Texture* texture = new sf::Texture();
     texture->loadFromFile(path);
     return texture;
   }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM