C++ 中模板化类型的类层次结构

Class hierarchy in templated types in C++

本文关键字:层次结构 类型 C++      更新时间:2023-10-16

我正在做一个简单的项目,其中有发布者从一个数据源读取并为订阅者构建事件。

事件将具有数据的唯一 PTR,订阅者将具有事件的共享 PTR。

我希望有一个事件的通用接口,以便订阅者可以订阅任意数据发布者。 但发布者只能发布一种类型的数据。

#include <memory>
#include <iostream>
class Data
{
};
class ChildData : public Data
{
};
template<typename T>
class Event
{
std::unique_ptr<T> _data;
};
void someFunc(Event<Data> event)
{
std::cout << "hello Word" << std::endl;
}
int main()
{
Event<ChildData> event();
someFunc(event);
return 0;
}

但是我收到以下编译器错误

/home/rory/dev/cpp_sandbox/main.cpp: In function ‘int main()’:
/home/rory/dev/cpp_sandbox/main.cpp:27:19: error: could not convert ‘event’ from ‘Event<ChildData> (*)()’ to ‘Event<Data>’
someFunc(event);
^
CMakeFiles/example.dir/build.make:62: recipe for target 'CMakeFiles/example.dir/main.cpp.o' failed
make[2]: *** [CMakeFiles/example.dir/main.cpp.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/example.dir/all' failed
make[1]: *** [CMakeFiles/example.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

这种事情在C++可能吗?

有问题的一行是这样的:

Event<ChildData> event();

根据最令人烦恼的解析规则,这被解释为函数声明。如果Event类具有初始化所有成员的默认构造函数,则可以省略括号。否则使用统一初始化语法:

Event<ChildData> event{};

此外,您可能必须使用std::moveevent传递给someFunc,因为Event由于数据成员std::unique_ptr而不可复制。此外,您还必须实现从Event<ChildData>Event<Data>的转换,这是someFunc所必需的。

我希望有一个事件的通用接口,以便订阅者可以订阅任意数据发布者。但发布者只能发布一种类型的数据。

从这个描述来看,Event模板似乎是多余的。Data后代的公共接口可以在Data类本身中描述,因此除非需要将事件与数据分开,否则仅处理数据会更容易。

为了区分不同的事件类型,您可以使用枚举。

enum class EventType
{
A,
B,
C
};
class Data
{
private:
const EventType m_type;
protected:
explicit Data(EventType type) : m_type(type) {}
public:
virtual ~Data() = default;
// Prohibit copying to avoid accidental slicing
Data(Data const&) = delete;
Data& opreator= (Data const&) = delete;
EventType get_type() const { return m_type; }
};
class ChildData :
public Data
{
public:
ChildData() : Data(EventType::A) {}
};
void receive(std::unique_ptr< Data > event)
{
switch (event->get_type())
{
case EventType::A:
{
std::unique_ptr< ChildData > child_event{ static_cast< ChildData* >(event.release()) };
// Process ChildData
}
break;
case EventType::B:
// ...
case EventType::C:
// ...
}
}
void publish(std::unique_ptr< Data > event);
int main()
{
std::unique_ptr< ChildData > event{ new ChildData() };
// Fill ChildData event
publish(std::move(event));
}