我想知道为什么您认为 Qt 工程师决定将setupUi()方法放入每种生成的形式中。

(对于那些不了解Qt如何工作的人:setupUi()是一种在动态内存中分配表单内每个按钮,texbox,小部件的方法。每个元素的引用都存储在指针成员变量中,该成员变量甚至没有初始化为nullptr和它放置在public:访问修饰符下,因此在您实际调用setupUi()之前,这看起来也有些危险。

在我的新观点看来,这完全违反了 RAII的原则,因为这意味着任何Ui_Whatever类实际上都不是由其构造函数调用构造的:构造函数只是分配该类本身,但是在我们调用Ui_Whatever::setupUi()之前它是不可用的。

可能是以下原因导致的设计原因:

  • 一个空的编译器生成的默认构造函数
  • 一种真正构造
  • 的方法

    (我问是因为我根本无法弄清楚自己的任何正当理由)

    提前致谢!!

    最佳答案

    我同意,这完全违反了RAII原则。但是我找到了一个相当简单的解决方法:

    template<typename UiClass> class QtRaiiWrapper : public UiClass
    {
    public:
        QtRaiiWrapper(QMainWindow *MainWindow)
        {
            setupUi(MainWindow);
        }
    };
    
    ...
    
    #include "ui_Main.h"
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
        ...
    private:
        // Ui_MainWindow m_Ui; // no RAII
        QtRaiiWrapper<Ui_MainWindow> m_Ui; // RAII
    };
    

    (它可能需要一些改进,但这是基本思想,对我来说效果很好。)

    关于该主题的更多讨论:

    Qt选择通过setupUi进行初始化的选择不仅为此组件缺少RAII,而且还可能使RAII对于程序的其他部分无法实现,这是很糟糕的。在我的情况下,另一个对象使用GUI元素的值进行初始化(这样,我可以在QtDesigner中定义初始值,而不是在其中使用伪值并在启动时覆盖它),但是不能使用RAII,因为GUI只能在MainWindow的构造函数的内部初始化。

    因此,我不同意库巴·奥伯(Kuba Ober)的意见,您无法完全控制何时确切地希望GUI初始化,因为您只能在构造函数主体而不是初始化列表中进行操作(在RAII之后,初始化列表是您可以在其中进行初始化的地方)也许大多数初始化都应该发生)。但是幸运的是,C++非常棒,我们可以为此编写一个解决方法(如上所述)。我还认为,这比更改uic的方式要好得多,因为一旦其他人尝试编译您的代码,他们就会看到很大的惊喜。

    10-05 22:43