模板类型推导的QObject多重继承的复杂性

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (149)

背景

对于初学者,我已经定义了一个空基Message类,其唯一目的是继承并创建具体TMessage实现。在Qt中,虽然可以将信号连接到仿函数(而不是Qt槽),但是信号不能是模板函数,所以我的解决方案是模拟Message类的关系,创建一个抽象Messenger类,带有void signal_Message(Message)信号和template <typename T> void slot_T(TMessage<T>)。然后我遇到了这个问题,使用不受支持的类型时,偶数代码在编译时失败,并显示一条错误消息: invalid initialization of reference of type Messenger<double>& from expression of type MessengerBag<int, char>

问题

考虑到我们使用6种不同类型,intfloatchardouble,一些enumstruct。这产生了sizeof96个字节!但是,考虑到所需的用法是用于具有超过50个用户定义类型的地方,每个地方都有自己独立维护的信号和插槽容器,看起来我的解决方案可以在大约相同的开销下执行相同的任务,但旁边没有维护费用。除了不再需要维护24个独立功能的明显好处之外,在复杂的继承方案的情况下甚至可能更多,这种方法是否存在缺点?做了一些初步测试后,我发现了MessengerBag基本上与钻石图案相反。每个析构函数都会相应调用,因此与复合结构相比,我几乎看不到任何缺点,复合结构需要另一个级别(我认为是不必要的和混淆的)间接。Qt本质上鄙视虚拟继承,并且在直接继承QObject的类中禁止它:因此我不能像我希望的那样使Mock虚拟化。

// Message.h
struct Message {};
template <typename T> struct TMessage {
    T t
};

// Messenger.h
struct Messenger : public QObject {
    Q_OBJECT
public:
    template <typename T> void slot_doSomethingWithMsg(const Message& msg){
        const auto& tmsg = static_cast<const TMessage<T>&>(msg);
        qDebug() << tmsg.t;
        // do something else... this is just example usage
    }
signals:
    void signal_sendMsg(const BaseMsg& msg);

// MessengerBag.h

template <typename T, typename... Args>
struct MessengerBag : TMessenger<T>, MessengerBag<Args...>{};

template <typename T> struct MessengerBag<T> : TMessenger<T>{};

// Manager.h

MessengerBag<int, char> messengerBag;

Manager(){
    QObject::connect(static_cast<TMock<int>*>(messengerBag),
                     &Mock::signal_sendMsg, 
                     static_cast<TMock<int>*>(messengerBag),
                     &Mock::slot_doSomethingWithMsg<int>);

    QObject::connect(static_cast<TMock<char>*>(messengerBag),
                     &Mock::signal_sendMsg, 
                     static_cast<TMock<char>*>(messengerBag),
                     &Mock::slot_doSomethingWithMsg<char>);

template <typename T> void slot_sendMsg(const TMessage<T>& msg){
    TMessenger<T>& messenger = messengerBag;
    messenger.signal_sendMsg(msg);
}

// main.cpp

auto* manager = new Manager();

TMessage<int> imsg{5};
TMessage<char> cmsg{'f'};

manager->slot_sendMsg(imsg);
manager->slot_sendMsg(cmsg);

正如所料,上面的例子输出5和'f',从而颠覆了模板信号和插槽的问题。但是,我在将来遇到任何可能的问题时遇到一些麻烦。一个问题当然QObject是无法访问的,因为它QObject仍然是未知的,组合解决方案可能会进行调解(使TMessenger委托Messenger,并在空的专业化中MessengerBag继承。,请对代码本身发表任意评论。

tl;dr

Qt信号调用函子,但信号不能是模板。QObject为了通过使用基Message类创建模板样式信号,让对象继承多个派生的模板类是否有任何缺点?这Message是信号的参数(因此信号和模板仿函数具有基本版本(之后仿函数将其转换为正确的类型T)。结构将像一包这些模板类一样,继承所有这些模板类。为了允许在任何时候向正确的模板类进行向上转换。

提问于
用户回答回答于

试试这个......

template<typename _Tb>
class _Ts : public _Tb 
{

public:
_Ts() {

// your connects

}

// any extensions to the qobject classes you are using
// note that you will need a common interface in your qobject subclasses... 
// meaning same named slots with different implementations 

};

热门问答

使用微信小程序也可以做腾讯云的标准视频直播吗?使用微信小程序做腾讯云的视频直播和im即时通讯可行吗?

美女视频一起走向共同富裕
推荐
支持的 IM部分,集成云通信 https://cloud.tencent.com/document/product/269/36838 标准直播部分,使用live-pusher和live-player标签,然后用云直播即可 https://cloud.tencent.com/do...... 展开详请

为什么我通过控制台vnc看到的界面和用vnc viewer看的的界面不一样???

HappyLau谈云计算专注于公有云,私有云解决方案,在kubernetes,openstack,kvm,ceph,linux,shell有丰富的实战经验。
推荐

控制台页面使用的是novnc,novnc是一种基于web页面使用的vnc客户端,详情可参考https://github.com/novnc/noVNC介绍,常规的vnc viewer是图形的客户端,所使用的依赖库有所不同,因此显示也不一样。

iOS在release下不走sendProcessBlock进度回调?

karis

腾讯 · 客户端开发工程师 (已认证)

Karis
推荐

请问是哪个版本的sdk呢,调用代码方便贴一下吗,最好能提供一个能复现的demo哈

API获取域名列表一直AuthFailure,code:4100?

推荐
推荐使用SDK进行调用:https://github.com/QcloudApi/qcloudapi-sdk-python 如果要自己写,也请参考下签名文档中python的代码示例,或者SDK中的源码:https://github.com/QcloudApi/qcloudapi-...... 展开详请

请问有图片鉴黄和文字甄别功能吗?现文字违规监控那么严格,有什么好的检测吗?

推荐已采纳
有的。 腾讯云 CDN 结合腾讯优图的深度学习图像识别技术,推出“图片鉴黄”服务,针对 CDN 全网分发的图片进行智能扫描,有效规避您的业务涉黄风险,目前全网免费公测中。参考文档:https://cloud.tencent.com/document/product/228/117...... 展开详请

使用文档遇到问题,可以找谁处理?

推荐已采纳
请叫我雷锋!腾讯云文档有“文档反馈”的功能,直接在文档页面就可以反馈,反馈还有 礼品 ~ 云+社区:问答.png ... 展开详请

所属标签

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励