Template classes C++ / Qt
Template classes C++ / Qt
我有一个应用程序,该应用程序将接收来自另一应用程序的消息。这些消息将是XML格式的字符串,并且它们将包含一个<messageType>
标记。消息类型会将此消息标识为内部消息的类型。下面的代码显示了我的内部消息结构。
namespace
Application1{
enum ApplicationAttributes{
ApplicationName = 1000,
Start,
Stop,
Pause,
Save,
Discard,
SelectRunway,
DoAlignment,
RedoAlignment,
AlignmentOK,
DoCalibrationStage1,
SetCalibrationStage1,
SetCalibrationStage2,
SetCalibrationStage3,
CancelCalibration,
CalibrationOK
};
struct Alignment{
int x;
int y;
int error;
};
struct Calibration{
int x;
int y;
int error;
};
}
对齐和校准是两种内部消息结构。
我想做的是构建一个"消息解释器",它将接收一个XML字符串,对其进行解码,并返回上面显示的任何一个结构;因此,如果<messageType>
是"alignment",则消息解释器将构建一个alignment结构,并返回该结构。
因此,最终,我将尝试制作一个模板函数,它可以根据我从<messageType>
中读取的内容返回任意结构。
我的目标明确吗?我的方法正确吗?
让我知道我是否应该澄清,或者我是否应该采取不同的方法。
我认为模板函数没有意义。你的输入总是一个字符串,C++不能仅根据返回类型来区分函数签名——所以我不知道模板会有什么帮助——类型参数是什么?
我建议让你的函数成为一个普通的函数,解析messageType并基于它分配一个结构——你可以为此使用任何你想要的结构。
诀窍是(在我看来)从同一个空基类派生所有内部消息类——然后你可以从函数返回一个指向该基类的指针,它将保存创建的任何类型。
最好在std::对中返回一个枚举和指针,您可以使用该对来确定创建的正确派生类型,这样您就可以使用static_cast将结果直接转换为正确的派生类型。
据我所知,您的结构在应用程序中是已知的,那么这个保存变体呢:
class Message {
public:
static Message Alignment (alignment_t const &);
...
Type type() const;
int alignment() const;
private:
Message (Type t);
assert_type (Type t, const char *msg) const;
private:
Type type_;
};
Message Message::Alignment (alignment_t const &alignment)
{
Message ret (Type::Alignment);
ret.alignment_ = alignment;
return ret;
}
void Message::assert_type (Type t, const char *msg) const
{
if (type() != t) throw std::runtime_error (msg);
}
int Message::alignment() const
{
assert_type (Type::Alignment,
"alignment_x() called for non-alignment-message");
return alignment_;
}
(无需验证即可编码,让您了解想法)
这在没有多态性的情况下工作(我在类似LISP语言的编译器中使用这种模式,多态树会导致更复杂的代码)。如果你更喜欢的话,你可以将其更改为返回"alignment_x()"等等。
完全动态的结构是不可能的,试图接近的解决方案将相当复杂。使用最易维护的解决方案。
如果您为每种类型编写一个工厂函数/函子,您可以将其与messageType
相关联(map<string, Factory*>
就足够了),但返回什么?
如果您不介意根据所有可能的消息类型使用顶级解码器,则可以返回某种有区别的并集或boost::variant
。
但是,解码器将如何处理这个返回值?如果它只是打开类型并在每种情况下调用特定于类型的回调,则可以通过将回调函数/函子直接附加到工厂来反转控制。
然后解码器不返回任何内容,它只是构造消息struct
并将其直接传递给处理程序。
简单的实现(好吧,这比我想象的要打字多):
class Decoder
{
public:
virtual ~Decoder();
virtual void decode(std::string const &xml) = 0;
};
template <typename Factory, typename Callback>
class SimpleDecoder: public Decoder
{
Factory factory;
Callback callback;
public:
SimpleDecoder(Factory f, Callback c)
: factory(f), callback(c)
{}
void decode(std::string const &xml)
{
callback( factory( xml ) );
}
};
std::map<std::string, Decoder*> factories;
template <typename F, typename C>
void registerSimpleDecoder(std::string const &n, F f, C c)
{
factories[n] = new SimpleDecoder(f, c);
}
void decodeXmlMessage(std::string const &messageType, std::string const &body)
{
factories[messageType]->decode(body);
}
使用QMetaObject::newInstance,这样您就可以创建一个QObject*,之后可以使用dynamic_cast 将其转换为您的类
class MyClass : public QObject{
public:
enum Type{ MyClassType = UserType + 1 }
Q_INVOKABLE MyClass();
}
Q_DECLARE_METATYPE ( MyClass )
然后,在您的XML解析代码中:
MyClass* myObject = (MyClass*) QMetaType::construct ( MyClass::MyClassType );
事情会解决的。
- Qt VTK交互风格的信号到小部件
- QT在错误的班级中寻找空位
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 如何在Qt窗口小部件中使用QStringView(或QStringRef)
- 如何在Qt C++中更改光标
- 如何在MS Visual Studio 2019中运行QT UI
- QT通过C++添加映射QML项目
- libssh 的函数在构建 libssh 时无法在 Qt 和 cmake 错误中找到
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 使用Qt C++计算类似Git的SHA1哈希
- Qt focusObjectChanged example?
- 如何在cpp文件之间切换窗口?在Qt中
- Qt和C++:将QLineEdit添加到QTabWidget中
- 从数据库实时显示QT c++中的数据
- Qt Quick-如何仅从c++代码与qml属性交互
- 无法使用Qt Creator在Windows中构建yaml-cpp
- 如何在Qt中取消捕获字符串
- Qt SQLite没有查询或参数计数不匹配
- Qt SQlite无法创建表