У меня есть шаблонный класс и подкласс шаблонного класса, чтобы реализовать функцию по-разному. Поскольку я хочу сохранить гибкость в наличии нескольких подклассов, я не непосредственно храню сам подкласс. В 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;}
Подкласс:
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;
}
Где-то в другом классе я храню экземпляр Loader:
Loader<Res> * loader;
Моя проблема в том, что даже если я назначаю экземпляр TextureLoader этой переменной загрузчика, вызывается только функция суперкласса, но не фактически реализованная функция подкласса. Как я могу добиться вызова функции подкласса, сохраняя при этом гибкость при наличии нескольких загрузчиков?
Возможно, вам не требуется наследование - похоже, что вам может понадобиться специализация:
template<>
sf::Texture* Loader<sf::Texture>::loadFromFile(std::string path) {...}
Теперь просто используйте Loader<sf::Texture>
где перед тем, как вы планируете использовать TextureLoader
. Или, typedef последнего к первому.
Ваша функция никогда не отображается как виртуальная. Тем не менее, вы должны действительно сделать его абстрактным, потому что он не имеет смысла, не перезаписывая его:
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;
}
};
Для того чтобы динамическая отправка имела место, вам нужно объявить функцию-член virtual в базовом классе. Вы также захотите объявить деструктор виртуальным, чтобы убедиться, что производные классы правильно очищены, когда они удалены с помощью типа базового класса.
template<class Res> class Loader {
public:
virtual ~Loader() [}
virtual Res* loadFromFile(std::string filePath);
};
loadFromFile
должен бытьvirtual