当前位置: 首页 > 知识库问答 >
问题:

变量模板继承,成员函数重载

归星驰
2023-03-14

我试图重写模板类http://docs.ros.org/hydro/api/rviz/html/c/message__filter__display_8h_source.html使用多种消息类型,使用变量模板。

我的第一个问题是如何使用可变模板重写下面的示例代码,以便它可以用于任意数量的模板参数,而不仅仅是2个。

我需要在家长类:

  • 每个模板类型的虚拟成员函数processMessage
  • 每个模板类型的每个incomingMessage的成员函数
  • 每个模板类型的成员变量。(稍后将成为ROS中该消息类型主题的subscriber)

因此,如果使用2个模板类型调用,变量基类应编译为如下内容:

包括:

#include<string>
#include<sstream>
#include<iostream>
using namespace std;

工作代码(常用模板):

template<class MessageType1,class MessageType2> class Parent{
public:

    Parent() : messages_received_(0){}

    virtual void processMessage(MessageType1 msg) = 0;
    virtual void processMessage(MessageType2 msg) = 0;

    void incomingMessage(MessageType1 msg){
        processMessage(msg);
        incr();
    }

    void incomingMessage(MessageType2 msg){
        processMessage(msg);
        incr();
    }

private:
    void incr(){
        cout<<"received "<<++messages_received_<<endl;;
    }

    MessageType1 sub1_;
    MessageType2 sub2_;

    int messages_received_;
};

不工作(可变):

template<class... Elements> class Parent;
template<> class Parent<>{};

template<class Head, class... Tail> class Parent<Head, Tail...> : public Parent<Tail...> {
public:
    Parent() : messages_received_(0){}

    virtual void processMessage(Head msg) = 0;

    void incomingMessage(Head msg){
        processMessage(msg);
        incr();
    }

private:
    void incr(){
        cout<<"received "<<++messages_received_<<endl;;
    }

    Head sub1_;

    int messages_received_;
};

编译失败:

g++ variadic.cpp --std=c++0x
variadic.cpp: In function ‘int main()’:
variadic.cpp:52:33: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
/usr/include/c++/4.6/bits/basic_string.h:485:7: error:   initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]’ [-fpermissive]

所以我猜测,不知何故,成员函数ProcMessage仅编译为ProcMessage(std::string s),而不是重载版本ProcMessage(int a)

用法示例:

class Child : public Parent<std::string, int> {
public:
    void processMessage(std::string msg){
        cout<<"string: "<<msg<<endl;
    }

    void processMessage(int msg){
        cout<<"int: "<<msg<<endl;
    }
};

int main()
{
        Child myMfd;

        myMfd.incomingMessage(42);
        myMfd.incomingMessage("abc");

        return 0;
}

如何解决此问题?

共有3个答案

冯德宇
2023-03-14

子项继承父项

template<>
class Parent<int>
    : public Parent<>
{
    // ...
    virtual void processMessage(int msg) = 0;

    void incomingMessage(int msg)
    {
        processMessage(msg);
        incr();
    }
    // ...
};

template<>
class Parent<std::string, int>
    : public Parent<int>
{
    // ...
    virtual void processMessage(std::string msg) = 0;

    void incomingMessage(std::string msg)
    {
        processMessage(msg);
        incr();
    }
    // ...
};

class Child : public Parent<std::string, int>
{
    // ...

Parent

那怎么办呢只需通过“使用”它来取消隐藏超类的incomingMessage

template<class Head, class... Tail>
class Parent<Head, Tail...>
    : public Parent<Tail...>
{
public:
    using Parent<Tail...>::incomingMessage;
    // ...

当然,虚拟根目录父目录也应该有输入消息

template <> class Parent<>
{
public:
    // to forbid call dummy `incomingMessage`.
    class dummy_ { private: dummy_() = delete; };
    void incomingMessage(dummy_);
};

谷梁振
2023-03-14

问题是的一个专门化中incomingMessage的声明隐藏了基类专门化中的声明;因此,您的类中唯一可用的重载是直接基类。

最简单的解决方案是向Parent添加一个using声明,以使所有重载可用:

using Parent<Tail...>::incomingMessage;

您还需要在“根”专门化中声明以支持这一点:

template<> struct Parent<>{
    void incomingMessage(); // No need for a definition
};

您可能还希望将消息\u接收到的消息\u移动到“根”专门化中,这样所有消息类型都有一个计数器,而不是每种类型都有一个计数器。如果您这样做,请记住它是一个依赖名称,因此派生专业将不得不将其称为this-

艾跃
2023-03-14

我还没有对此进行测试,但应该在以下方面进行测试:

template<typename ...Args> class Parent;

template<> class Parent<> {

public:
    void incr();
    void incomingMessage() {}
};

template<typename MessageType, typename ...Args>
class Parent<MessageType, Args...> : public Parent<Args...> {

public:
    virtual void processMessage(MessageType msg)=0;

    using Parent<Args...>::incomingMessage;
    void incomingMessage(MessageType msg)
    {
        processMessage(msg);
        this->incr();
    }
};

这并不完美,您需要从上一个类“向上传播”incomingMessage,以便它在“顶级范围”中正确解析,因此需要根超类中的丑陋incomingMessage()。再多做一点工作,可能也有办法解决这个问题。

 类似资料:
  • 我试图在变量函数模板上使用'decltype'来获取其返回值类型,然后使用它来定义成员变量。但我一直在犯这样的错误: 基本上,decltype失败并将声明为int,而不是推断的返回类型。 它的工作原理是当我提供的所有参数的值,但这不是我要找的行为。因为我不知道该函数有多少参数,所以它必须保持为可变模板函数。 我计划如何使用类模板的示例: 如果我没有任何成员变量,并使用作为: 它编译,因此我相信能够

  • 我试图用成员模板函数实现一个可变类模板,其模板参数独立于类模板参数,但在定义成员模板时遇到了问题。 我将问题简化为尝试编译此文件(抱歉,无法进一步简化): 在尝试编译(C 11)时,我遇到以下错误: 我很确定它归结为第一个和第五个错误,但不知道我做错了什么。为什么

  • 我有一个模板化的C++类,它也有一个模板化的成员函数。这个成员函数的模板参数以特定的方式依赖于类的模板参数(请参阅下面的代码)。我正在为其模板参数的两个不同值实例化(而不是专门化)该类。一切都在这一点上进行。但是,如果我调用模板化的成员函数,对第一个实例化对象的调用只会编译,而不会编译第二个。似乎编译器没有为模板类的第二次实例化实例化模板化成员函数。我正在使用“g++filename.cpp”编译

  • Jinja 最为强大的地方在于他的模板继承功能,模板继承允许你创建一个基础的骨架模板, 这个模板包含您网站的通用元素,并且定义子模板可以重载的 blocks 。 听起来虽然复杂,但是其实非常初级。理解概念的最好方法就是通过例子。 基础模板 在这个叫做 layout.html 的模板中定义了一个简单的 HTML 文档骨架,你可以 将这个骨架用作一个简单的双栏页面。而子模板负责填充空白的 block:

  • 模板继承可以减少页面内容的重复定义,实现页面内容的重用 典型应用:网站的头部、尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义 block标签:在父模板中预留区域,在子模板中填充 extends继承:继承,写在模板文件的第一行 定义父模板base.html { % block block_name % } 这里可以定义默认值 如果不定义默认值,则表示空字符串 { %

  • Jade 支持通过 block 和 extends 关键字来实现模板继承。 一个块就是一个Jade的"block" ,它将在子模板中实现,同时是支持递归的。 Jade 块如果没有内容,Jade会添加默认内容,下面的代码默认会输出block scripts, block content, 和 block foot. html head h1 My Site - #{title}