我有一个像这样定义的模板类:
template <class T>
class Command {
public:
virtual T HandleSuccess(std::string response) = 0;
virtual std::string FullCommand() const = 0;
// ... other methods here ...
};
C ++是否允许我创建模板类的非模板子类?我的意思是我可以做这样的事情:
class NoopCommand : public Command<NoopResult> {
public:
NoopResult HandleSuccess(std::string response);
std::string FullCommand() const;
// ... other methods here ...
};
因为它对我不起作用,因为它说以下虚函数是未定义的:
T admix::Command<T>::HandleSuccess(std::string) [with T = admix::NoopResult]
std::string admix::Command<T>::FullCommand() const [with T = admix::NoopResult]
如何为给定的T专门定义它们?
答案 0 :(得分:4)
正如我们在IRC中所知,那是因为你有
(以下是我对你的问题的早期版本的怀疑 - 我保留它以供进一步考虑并保持意见有意义)
<子> 我认为这里的问题是编译器可以自由地实例化类模板的任何虚函数成员,即使它没有被使用(即没有被调用)。实例化一个函数需要提供一个函数定义。尝试在标题中添加它,编译器将在其中找到它们并实例化以下定义:
template<typename T>
T Command<T>::HandleSuccess(std::string response) { /* put some default action ... */ }
template<typename T>
std::string Command<T>::FullCommand() const { /* put some default action ... */ }
C ++标准14.7.1/9
:
实现不应隐式实例化功能模板,成员模板,非虚拟 成员函数,成员类或不需要实例化的类模板的静态数据成员。如果虚拟成员函数不会被实例化,则实现是否隐式实例化类模板的虚拟成员函数是未指定的。
答案 1 :(得分:3)
“虚函数未定义”表示您尚未定义NoopCommand :: HandleSuccess和NoopCommand :: FullCommand的函数体。
以下内容可以解决您的问题。
class NoopCommand : public Command<NoopResult> {
public:
NoopResult HandleSuccess(std::string response) {}
std::string FullCommand() const {}
// ... other methods here ...
};
或者你有一个NoopCommand.cpp,确保它包含在你的构建过程中。
答案 2 :(得分:2)
您使用的模式被广泛称为“Curiously Recurring Template Pattern”。所以,是的,你可以这样做 我想不出它为什么不编译的原因。
答案 3 :(得分:0)
您提供的代码为我编译,没有错误(添加struct NoopResult { };
后)。也许您遗漏的代码存在问题?
答案 4 :(得分:-1)
litb昨晚在## c ++上找到了解决方案。
问题是我正在将NoopCommand传递给这样的函数:
void SendCommand(Command<T> command);
当我应该签名时:
void SendCommand(Command<T>& command);
进行更改可以编译所有内容。