Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Qt是否支持虚拟纯插槽?_C++_Qt_Inheritance_Signals Slots - Fatal编程技术网

C++ Qt是否支持虚拟纯插槽?

C++ Qt是否支持虚拟纯插槽?,c++,qt,inheritance,signals-slots,C++,Qt,Inheritance,Signals Slots,我在Qt中的GUI项目有很多“配置页面”类,它们都直接从QWidget继承 最近,我意识到所有这些类都共享2个公用插槽(loadSettings()和saveSettings()) 关于这一点,我有两个问题: 用这两个插槽作为虚拟纯方法编写一个中间基类抽象类(让我们把它命名为BaseConfigurationPage)有意义吗?(每个可能的配置页面都将始终有这两种方法,因此我会说“是”) 在我对代码进行重大更改之前(如果必须的话):Qt支持虚拟纯插槽吗?有什么我应该知道的吗 下面是一个描述一

我在
Qt
中的GUI项目有很多“配置页面”类,它们都直接从
QWidget
继承

最近,我意识到所有这些类都共享2个公用插槽(
loadSettings()
saveSettings()

关于这一点,我有两个问题:

  • 用这两个插槽作为虚拟纯方法编写一个中间基类抽象类(让我们把它命名为
    BaseConfigurationPage
    )有意义吗?(每个可能的配置页面都将始终有这两种方法,因此我会说“是”)
  • 在我对代码进行重大更改之前(如果必须的话):Qt支持虚拟纯插槽吗?有什么我应该知道的吗
下面是一个描述一切的代码示例:

class BaseConfigurationPage : public QWidget
{
  // Some constructor and other methods, irrelevant here.

  public slots:

    virtual void loadSettings() = 0;
    virtual void saveSettings() = 0;
};

class GeneralConfigurationPage : public BaseConfigurationPage
{
  // Some constructor and other methods, irrelevant here.

  public slots:

    void loadSettings();
    void saveSettings();
};

是的,就像普通C++纯虚方法一样。MOC生成的代码确实调用了纯虚拟插槽,但这没关系,因为基类无论如何都不能实例化

再次,就像常规C++纯虚方法一样,在给出方法实现之前,不能实例化类。 有一件事:在子类中,实际上不需要将重写的方法标记为插槽。首先,它们已经实现为基类中的插槽。其次,您只是为MOC和编译器创建了更多的工作,因为您添加了(一点点)更多的代码。琐碎,但不管怎样


因此,开始吧。

仅在BaseConfigurationPage中使用插槽

class BaseConfigurationPage : public QWidget
{
  // Some constructor and other methods, irrelevant here.

  public slots:

    virtual void loadSettings() = 0;
    virtual void saveSettings() = 0;
};

class GeneralConfigurationPage : public BaseConfigurationPage
{
  // Some constructor and other methods, irrelevant here.

    void loadSettings();
    void saveSettings();
};

其他人已经解释了虚拟、继承和插槽的机制,但我认为我应该回到这一部分或问题:

写一个中间基类抽象类有意义吗。。。将这两个插槽作为虚拟纯方法

我想说的是,只有当您使用该抽象,或者换句话说,如果您的代码在一个或多个
BaseConfigurationPage
s上运行,而不考虑实际类型时,这才有意义

假设您的对话框代码非常灵活,可以容纳
std::vector m_页面
。加载代码可能如下所示。在这种情况下,抽象基类是有意义的

void MyWizard::loadSettings()
{
    for(auto * page : m_pages)
    {
        page->loadSettings();
    }
}
但是,另一方面,假设您的对话框实际上是相当静态的,并且具有
IntroPage*m_IntroPage;客户页面*m_客户页面;ProductPage*m_ProductPage。加载代码可能如下所示

void MyWizard::loadSettings()
{
    m_introPage->loadSettings();
    m_customerPage->loadSettings();
    m_productPage->loadSettings();
}
在这种情况下,
BaseConfigurationPage
绝对不会给您带来任何好处。它增加了复杂性,增加了代码行,但没有增加表达能力,也不能保证正确性

没有更多的背景,两种选择都不一定更好

作为学生或新程序员,我们通常被教导识别和抽象掉重复,但这实际上是一种简化。我们应该寻找有价值的抽象概念。重复可能暗示需要抽象,也可能只是一个信号,表明有时实现有模式。仅仅因为注意到一个模式而引入一个抽象是一个很常见的设计陷阱

海豚的设计和鲨鱼的设计非常相似。人们可能会试图插入一个
鱼雷形状的游泳者
基类来捕捉这些共性,但这种抽象是否提供了价值,或者在以后实现
呼吸()
,“乳酸()
生长骨架()”时,它实际上会增加不必要的摩擦


我意识到这是一个关于基于一些简单示例代码的子问题的长篇大论,但我最近在工作中多次遇到这种模式:基类只捕获重复而不增加价值,但会妨碍将来的更改。

感谢您的精确回答!我将尽快对此进行测试;)从子类中删除插槽规范可防止moc调用子类和基类!-谢谢你,伙计!至少在Qt5中,如果您使用的是
connect
obj-ptr、member-func-ptr、obj-ptr、member-func-ptr
版本,则不需要声明任何插槽。必须添加一些非常奇怪的行为:当您在子类的头中将重写的方法标记为插槽时,插槽始终被调用,即使与插槽之间没有连接。算了吧!!!我也这么做了,但是我得到了“slot name”覆盖了一个成员函数,但没有标记为“override”Yes,
loadSettings
saveSettings
应该在
GeneralConfigurationPage
中用
override
声明,以确保它们确实覆盖了某些内容。