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
声明,以确保它们确实覆盖了某些内容。