是否可以将非模板类子类化为模板类?

发布于 2024-08-09 18:06:18 字数 751 浏览 3 评论 0原文

我有一个如下定义的模板类:

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

I have a template class defined like so:

template <class T>
class Command {
public:
    virtual T HandleSuccess(std::string response) = 0;
    virtual std::string FullCommand() const = 0;
    // ... other methods here ...
};

Will C++ allow me to create a non-template subclass of a template class? What I mean is can I do something like this:

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

As is that is not working for me because it says the following virtual functions are undefined:

T admix::Command<T>::HandleSuccess(std::string) [with T = admix::NoopResult]
std::string admix::Command<T>::FullCommand() const [with T = admix::NoopResult]

How can I specifically define them for the given T?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浮华 2024-08-16 18:06:18

正如我们在 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

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

As we figured out in IRC, that was because you have

  1. Made your functions non-pure
  2. Sliced the derived object part. So the base class functions were called because the object wasn't a complete derived object anymore.

(Below follows my suspicion on earlier versions of your question - i keep it for further consideration and to keep the comments meaningful)



I think the issue here is that the compiler is free to instantiate any virtual function member of a class template even if it's not used (i.e not called). Instantiating a function will need a function definition to be provided. Try to add this in the header, where the compiler will find them and instantiate a definition from:

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++ Standard 14.7.1/9:

An implementation shall not implicitly instantiate a function template, a member template, a non-virtual
member function, a member class or a static data member of a class template that does not require instantiation. It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.

窝囊感情。 2024-08-16 18:06:18

“虚拟函数未定义”表示您尚未定义NoopCommand::HandleSuccess 和NoopCommand::FullCommand 的函数体。

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

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

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

"virtual functions are undefined" means you have not defined the function bodies of NoopCommand::HandleSuccess and NoopCommand::FullCommand.

The following should solve your problem.

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

Or you you have a NoopCommand.cpp, make sure it's included in your build process.

许仙没带伞 2024-08-16 18:06:18

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

The pattern you use is widely known as the "Curiously Recurring Template Pattern". so, yes, you can do that.
I can't think of a reason why it does not compile.

遮了一弯 2024-08-16 18:06:18

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

The code you gave compiles for me, without errors (after adding a struct NoopResult { };). Maybe there's a problem in the code you left out?

慈悲佛祖 2024-08-16 18:06:18

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

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

void SendCommand(Command<T> command);

当我应该将签名设置为:

void SendCommand(Command<T>& command);

进行更改允许所有内容编译。

litb found the solution on ##c++ last night.

The issue was I was passing a NoopCommand to a function like this:

void SendCommand(Command<T> command);

When I should have made the signature this:

void SendCommand(Command<T>& command);

Making that change allows everything to compile.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文