【问题标题】:C++ Qt program design issueC++ Qt程序设计问题
【发布时间】:2017-09-24 08:01:01
【问题描述】:

在 C++ Qt 中有一个类QWidget

  • A继承QWidget并增加了一些特性
  • B继承A并增加了一些特性
  • C继承B并增加了一些特性,C必须是QWidget类型并且应该做所有B做的事情

由于某种原因C 的行为不如预期,我必须重写类C。我无法将代码修改为 B 创建类。

我该如何解决这个问题?有什么设计模式,还是别的什么?

如果我尝试继承QWidgetB,一个多重继承,会有两个QWidget导致问题(QObject - moc不允许这样做)。

如果我从QWidget 继承并将B 的对象传递给C 的构造函数,那么B 执行的任何操作都适用于通过B 的另一个QWidget,这是不希望的,所有功能B 提供的应该适用于我的CQWidget

【问题讨论】:

  • 首先想到的是看看Decorator pattern。此处的其他参考:Decorator Design Pattern.
  • 由于某种原因,C 的行为不符合预期也许你应该问一个问题(显示一些细节,以便我们可以提供帮助)。如果我们知道问题所在,也许我们可以解决它。
  • 类 C 继承 B 并增加了一些特性,C 必须是 QWidget 类型并且应该做所有 B 做的事情 确实应该这没问题。 C 将是其父级的 QWidget
  • @drescherjm 问题是 B 正在对 Qwidget 的布局做一些事情,导致用户界面不正确,而我没有 B 的来源。
  • @PhilBrubaker ,我已经完全看到了装饰器设计模式,但它看起来并不能解决我的问题。它说将一个类的对象传递给另一个类,如果我将 B 的对象传递给 C 的构造函数,则 B 在内部对其 QWidget 所做的操作将持续存在。

标签: c++ qt class-design


【解决方案1】:

假设有一个温度传感器,当它与机器断开连接时,B 类在它拥有的QWidget 的整个区域上绘制一个内容阻止图像,我可以监控传感器连接/断开连接并假设C的乐趣。 OnDisconnect() 被调用,我将调用 B::OnDisconnect()B 将自己绘制阻止图像 QWidget,而不是 C 拥有的图像。

这与 C++ 相当不灵活的方法实现继承有关,例如,到通用 LISP 对象系统。

由于B 的遮蔽始终位于B 的内容之上,因此您实际上需要B 提供覆盖其内容之上的覆盖,即使@987654334 @ 在派生类中被覆盖。

有关简单示例,请参阅this answer,或有关具有模糊图形效果的叠加层,请参阅 another answer

这很容易通过让B 为其自身添加一个可选的叠加小部件来实现。

例子:

class OverlayWidget; // from https://stackoverflow.com/a/19367454/1329652    

class ObscureOverlay : public OverlayWidget
{
public:
  ObscureOverlay(QWidget * parent = {}) : OverlayWidget{parent} {}
protected:
  void paintEvent(QPaintEvent *) override {
    QPainter p{this};
    p.fillRect(rect(), {Qt::black});
  }
};

class A : public QWidget {
  ...
protected:
  void paintEvent(QPaintEvent *) override { ... }
};

class B : public A {
  ...
  ObscureOverlay m_obscure{this};
public:
  B() {
    m_obscure.hide();
  }
  Q_SLOT void OnDisconnect() {
    m_obscure.show();
    ...
  }
};

class C : public B {
  ...
protected:
  void paintEvent(QPaintEvent * event) override {
    B::paintEvent(event);
    ...
  }
};

如果您没有B 的源代码,您可以将叠加层添加到C,在被遮挡时复制原始B 的功能。 Qt 的所有插槽实际上都是虚拟的,因此如果您将C 传递给期望B 并连接到其OnDisconnect 插槽的人,则将调用C 的插槽。

class C : public B {
  Q_OBJECT
  ...
  ObscureOverlay m_obscure{this};
public:
  explicit C(QWidget * parent = {}) : B{parent} {
    m_obscure.hide();
  }
  Q_SLOT void OnDisconnect() { // slots are effectively virtual
    m_obscure.show();
    B::OnDisconnect();
  }
protected:
  void paintEvent(QPaintEvent * event) override {
    B::paintEvent(event);
    QPainter p{this};
    ...
  }
};

【讨论】:

    猜你喜欢
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多