2

我有一个这样定义的模板类:

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 专门定义它们?

4

5 回答 5

4

正如我们在 IRC 中发现的那样,那是因为你有

  1. 使您的功能不纯
  2. 切片派生对象部分。因此调用基类函数是因为对象不再是完整的派生对象。

(以下是我对您问题早期版本的怀疑 - 我保留它以供进一步考虑并保持评论有意义)


我认为这里的问题是编译器可以自由地实例化类模板的任何虚函数成员,即使它没有被使用(即没有被调用)。实例化一个函数需要提供一个函数定义。尝试将其添加到标头中,编译器将在其中找到它们并从以下位置实例化定义:

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

实现不应隐式实例化不需要实例化的类模板的函数模板、成员模板、非虚拟成员函数、成员类或静态数据成员。如果虚拟成员函数不会被实例化,则未指定实现是否隐式实例化类模板的虚拟成员函数。

于 2009-10-26T01:29:50.970 回答
3

“virtual functions are undefined”是指没有定义 NoopCommand::HandleSuccess 和 NoopCommand::FullCommand 的函数体。

以下应该可以解决您的问题。

class NoopCommand : public Command<NoopResult> {
public:
    NoopResult HandleSuccess(std::string response) {}
    std::string FullCommand() const {}
    // ... other methods here ...
};

或者你有一个 NoopCommand.cpp,确保它包含在你的构建过程中。

于 2009-10-26T01:34:34.563 回答
2

您使用的模式被广泛称为“奇怪重复的模板模式”。所以,是的,你可以这样做。
我想不出它无法编译的原因。

于 2009-10-26T01:15:08.837 回答
0

您提供的代码为我编译,没有错误(添加后struct NoopResult { };)。也许您遗漏的代码有问题?

于 2009-10-26T01:28:45.060 回答
-1

litb 昨晚在##c++ 上找到了解决方案。

问题是我将 NoopCommand 传递给这样的函数:

void SendCommand(Command<T> command);

当我应该签名时:

void SendCommand(Command<T>& command);

进行该更改可以编译所有内容。

于 2009-10-26T14:10:39.150 回答