C++ 具有重载方法的可变数据结构

C++ 具有重载方法的可变数据结构,c++,c++11,templates,variadic-templates,overloading,C++,C++11,Templates,Variadic Templates,Overloading,我有一个可以发布/订阅多种消息类型的系统。添加新类型时,必须更新大量文件以添加对新方法类型的支持 是否可以用一个泛型的纯虚方法声明一个C++类作为一个可变数据结构?< /P> 编译C++程序时,“ MessageB >第二种发布方法的声明被“ MessageA < /代码>”所隐藏。 main.cpp:57:41:错误:调用'ippublisher::publish(MessageB)'publisher->publish(MessageB{“world”}没有匹配的函数 这与GCC和Clan

我有一个可以发布/订阅多种消息类型的系统。添加新类型时,必须更新大量文件以添加对新方法类型的支持

是否可以用一个泛型的纯虚方法声明一个C++类作为一个可变数据结构?< /P>

编译C++程序时,“<代码> MessageB <代码> >第二种发布方法的声明被“<代码> MessageA < /代码>”所隐藏。 main.cpp:57:41:错误:调用'ippublisher::publish(MessageB)'publisher->publish(MessageB{“world”}没有匹配的函数

这与GCC和Clang一致,但Clang确实发出了有用的警告:

警告:“IPublishOne::publish”隐藏重载虚拟函数[-Woverloaded virtual]虚拟无效发布(const T&message)=0

既然MessageA和MessageB是不同的类型,为什么会发生方法隐藏

#include <iostream>
#include <memory>

using namespace std;

template <class...Ts>
struct IPublishOne;

template <class T>
struct IPublishOne<T>
{
    virtual void publish(const T& message) = 0;
};

template <class T, class... Ts>
struct IPublishOne<T, Ts...> : IPublishOne<Ts...>
{
    virtual void publish(const T& message) = 0;
};

struct MessageA
{
    std::string value;
};

struct MessageB
{
    std::string value;
};

struct IPublisher : public IPublishOne<MessageA, MessageB>
{
    virtual ~IPublisher() = default;
};

struct Publisher : public IPublisher
{

    void publish(const MessageA& message) override
    {
        std::cout << message.value << std::endl;
    }

    void publish(const MessageB& message) override
    {
        std::cout << message.value << std::endl;
    }
};

int main()
{
    const std::unique_ptr<IPublisher> publisher = std::make_unique<Publisher>();

    publisher->publish(MessageA{"hello"});

    // this produces compile error
    publisher->publish(MessageB{"world"});

    return 0;
}
#包括
#包括
使用名称空间std;
模板
结构IPublishOne;
模板
结构IPublishOne
{
虚拟无效发布(const T&message)=0;
};
模板
结构IPublishOne:IPublishOne
{
虚拟无效发布(const T&message)=0;
};
结构消息
{
std::字符串值;
};
结构消息B
{
std::字符串值;
};
结构IPPublisher:公共IPPublishOne
{
virtual~IPublisher()=默认值;
};
结构发布者:公共IPpublisher
{
无效发布(const MessageA&message)覆盖
{

std::cout问题在于在类中定义
publish()
方法会隐藏从基类继承的所有
publish()
方法

IPublishOne

template <class T, class... Ts>
struct IPublishOne<T, Ts...> : IPublishOne<Ts...>
{
   using IPublishOne<Ts...>::publish;  // <<<-------------

    virtual void publish(const T& message) = 0;
};
模板
结构IPublishOne:IPublishOne
{
使用IPublishOne::publish;//
既然MessageA和MessageB是不同的,为什么会发生方法隐藏
类型

您缺少最终覆盖器

IPublishOne::publish
覆盖
IPublishOne::publish
依据:

如果虚拟成员函数
vf
类基中声明,并且在
类派生
,直接或间接派生自
,成员 功能
vf
具有相同名称、参数类型列表、cv鉴定、, 和ref限定符(或缺少相同的限定符)作为
Base​::​声明vf
,然后
派生​::​vf
也是虚拟的(无论是否如此声明),并且 它覆盖
Base​::​vf

您需要的是:

结构IPublishOne
中指定最终重写器:

模板
结构IPublishOne:IPublishOne
{
使用IPublishOne::publish;//的最终重写器
//IPublishOne::发布
虚拟无效发布(const T&message)=0;
};

如果它没有编译,最好让我们也知道错误消息,而不仅仅是警告。为后代编辑,在GCC上添加编译错误。干杯。
template <class T, class... Ts>
struct IPublishOne<T, Ts...> : IPublishOne<Ts...>
{
    using IPublishOne<Ts...>::publish;  // final overrider for
                                        // IPublishOne<T>::publish
    virtual void publish(const T& message) = 0;
};