【问题标题】:c++/ qt - no such slot - Inheritancec++/ qt - 没有这样的插槽 - 继承
【发布时间】:2016-06-22 03:38:32
【问题描述】:

这段代码:

MyAxis *ax;
ax = static_cast<MyAxis*>(ui->customPlot->axisRect()->addAxis(QCPAxis::atLeft));
connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)),
        ax, SLOT(MyAxis::rescale(QCPRange)));

给我这个运行时错误:

QObject::connect: 在 plotwindow.cpp:267 中没有这样的插槽QCPAxis::MyAxis::rescale(QCPRange)

通常当我遇到这样的错误时,我会在类中添加Q_OBJECT 宏并运行qmake 来修复它,但这一次不起作用。

这是类的声明:

class MyAxis : public QCPAxis
{
    Q_OBJECT
public:
    void setRefAxis(QCPAxis *refAxis);
    void setScale(double newScale);


public Q_SLOTS:
    virtual void rescale(const QCPRange &range);

private:
    double scale;
    QCPAxis *ref;
};

将声明更改为public slots: 没有任何区别。

【问题讨论】:

  • 提示:使用 Qt Creator 自动完成来填写 SIGNAL 和 SLOT 宏。如果它拒绝,则说明某处有问题。如果它自动完成,您可以避免潜在的拼写错误。

标签: c++ qt signals-slots qcustomplot


【解决方案1】:

我认为你在这里尝试做的事情有问题:

ui->customPlot->axisRect()->addAxis(QCPAxis::atLeft)

返回 QCPAxis 而不是 MyAxis 类。假设 QCPAxiz 占用 100 字节的内存,而 MyAxis 占用 110 字节,那么您正在尝试这样做:

A_110_Byte_Type* p110Bytes = static_cast<110-bytes *> (<100-bytes>); // not real code!

我不明白它是如何工作的。您正在调用的函数返回一个 QCPAxis 并且您不能仅仅因为它们共享相同的基类而将其转换为 MyAxis ......这有点像拥有福特嘉年华并说,“现在它是法拉利" 只是因为它们具有相同的基本类型“汽车”。

所以目前我认为你陷入了未定义的行为......

你想做什么? - 您可以将 QCPAxis 的值复制到您的 MyAxis 中(使用复制构造函数 - 我认为您需要其中一个来执行此操作)

【讨论】:

  • 不,这不是问题(这也是按名称连接即使在 Qt5 中仍然有用的部分原因)。 connect() 将使用运行时元对象来查找ax 的槽。真正的问题是SLOT 宏需要一个unqualified 方法名,即SLOT(rescale(QCPRange)) 而不是SLOT(MyAxis::rescale(QCPRange))
  • 不,我错了;这的问题!简单地铸造(使用static_cast&lt;&gt;(),呃!)不会将一个对象变成另一个对象。如果 Krzysztof 使用了qobject_cast&lt;&gt;(),他的错误会更加明显。我猜错误编写的SLOT() 宏是对问题的反复试验“修复”的一部分......
  • @TobySpeight... 我必须给你 +1 与自己争论 :)) ,是的,我同意我认为第一个问题是“红鲱鱼”
【解决方案2】:

您不能只将现有轴转换为MyAxis*。您需要实例化一个新的 MyAxis 并将其分配给图形:

QCPGraph *graph = new QCPGraph(this);
MyAxis *ax = new MyAxis(graph);
graph->setValueAxis(ax);
connect(...);

未来提示:避免使用static_cast&lt;&gt;(),其中有检查选项(此处为qobject_cast&lt;&gt;(),否则为dynamic_cast&lt;&gt;())。这将有助于识别无效假设。

【讨论】:

    【解决方案3】:

    Qt 存储了一些关于继承自QObject 的类的元信息。这些信息之一是类的槽。通过静态转换对象,这些元信息不会在转换中更新,因此您转换的对象的元信息不包含您在 MyAxis 类中实现的插槽。这就是为什么它无法在运行时将信号连接到投射的对象。即使您在 MyAxis 类中重新实现了一个虚拟槽,通过静态转换您的对象,新转换的对象的槽指向旧槽并且不会升级为指向重新实现的槽。

    更新: 通过使用qobject_cast(这是 Qt 对象的安全转换方式),您可以看到转换的对象为 NULL。

    【讨论】:

    • qobject_cast 替换static_cast 是个好主意,但它不会使代码工作。它可以通过给出一个空指针来诊断问题,所以这绝对是可取的,但问题是所指对象不是MyAxis - 他需要解决这个问题。
    【解决方案4】:
    1. Qt 的 moc-generator 是非常严格的:所以用同样的写法 签名:

      connect(..., SLOT(...(const QCPRange &)));
      
    2. 在其中一个 h 文件中缺少一条语句:

          Q_DECLARE_METATYPE(QCPRange)
      

    【讨论】:

    • 使用 Qt 4 连接语法时,首选规范化槽签名。因此connect(..., SLOT(...(QCPRange)));const&amp; 是多余的:从 connect 调用的签名规范器无论如何都会删除它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    相关资源
    最近更新 更多