2009-10-26 54 views
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?

+0

这是由编译器或链接器发出的错误吗? – 2009-10-26 01:17:10

+0

错误来自编译器。 – 2009-10-26 01:18:03

+0

什么编译器和版本?在编译器上我尝试了(gcc 4.2.1 for Darwin),它为我编译干净。 – 2009-10-26 01:22:48

回答

-1

昨天晚上,litb在## C++上找到了解决方案。

的问题是我经过一个NoopCommand以这样的函数:

void SendCommand(Command<T> command); 

当我应该让签名这样的:

void SendCommand(Command<T>& command); 

做出这样的转变让一切编译。

2

您使用的图案被广泛称为“Curiously Recurring Template Pattern”。所以,是的,你可以做到这一点。
我想不出为什么它不编译的原因。

+0

其实这个错误只是在输入问题时出现的,它在代码中有参数。 – 2009-10-26 01:16:40

+0

函数定义是否在.cpp文件中,而不是.h? – 2009-10-26 01:22:45

0

您给出的代码为我编译,没有错误(在添加struct NoopResult { };后)。也许你在代码中遗漏了一个问题?

+0

你有没有包含一些试图实例化类的代码?该类被编译器视为抽象类。 – 2009-10-26 01:30:13

+0

是的。如果'HandleSuccess'和'FullCommand'的主体当然缺失,可能会有链接时间问题 - 我认为你的错误来自编译时间,但既然你接受了其他答案,我猜他们是来自链接器? – bdonlan 2009-10-26 02:39:22

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

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

+0

我给了这两种方法的默认版本,但现在我有一个问题。代码调用默认版本而不是子类的重写版本,这意味着它不会考虑子类中的'NoopResult HandleSuccess(std :: string response)'来覆盖超类。 – 2009-10-26 02:55:33

+2

正如我们在IRC中发现的那样,那是因为你有1)使得你的函数不是纯粹的2)对派生的对象部分进行切片。所以基类函数被调用,因为该对象不再是一个完整的派生对象。 – 2009-10-26 05:18:38

+1

这有什么关系?是的,根据14.7.1/9,编译器可以自由实例化'命令 :: HandleSuccess(std :: string)'。但它只是一个将被实例化的声明。由于这是一个纯粹的虚拟声明,随后缺乏定义并不是错误。 – MSalters 2009-10-26 11:03:36

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,确保它包含在你的构建过程中。

+0

我已经定义了它们。我还定义了超类的默认版本,而不是使其成为纯虚拟的。但是,我的默认版本正在被调用,而不是在子类中重写的定义。 – 2009-10-26 02:56:37

+0

什么是你的定义 NoopResult HandleSuccess(std :: string response); 和 std :: string FullCommand()const; 以及你如何援引他们? – lyxera 2009-10-27 04:44:04

相关问题