C++ Qt 派生类

Posted

技术标签:

【中文标题】C++ Qt 派生类【英文标题】:C++ Qt Derived Classes 【发布时间】:2014-07-14 02:04:05 【问题描述】:

我正在尝试学习 Qt 和 C++,但在理解 C++ 这个关键工作时遇到了一些麻烦。我已经看到了从 QMainWindow 派生类然后在类成员函数中添加 QMenu 的示例。一个例子是本页描述的“简单菜单”程序:

http://www.zetcode.com/gui/qt4/menusandtoolbars/

在该示例中,使用以下命令创建退出操作

QAction *quit = new QAction("&Quit", this);

但是,假设我还想从 QMenu 派生一个类并使用它来创建我的菜单。

我的菜单.h

class MainWindow;   // forward declaration

class MyMenu : QMenuBar

public:
    MyMenu(MainWindow *main_window);

;

我的菜单.cpp

#include "mymenu.hpp"

MyMenu::MyMenu(MainWindow *main_window) : QMenuBar()

    QAction *quit = new QAction("&Quit", main_window);  // Notice here I replaced
                                                        // 'this' with 'main_window'
    QMenu = *file;
    file = menuBar()->addMenu("&File");
    file->addAction(quit);
    connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));

不幸的是,这不起作用,因为 QAction 期望 QObject 作为父对象。说了这么多,有几件事对我来说没有意义:

    如果 MainWindow 类继承自 QMainWindow,那不是让 'MainWindow' 成为 QObject 吗? 从 MainWindow 类中传递 'this' 到 QAction 与传递 'main_window' 有什么区别(据我所知)它也是从 MyMenu 类中指向实例的指针?

对于这样一个冗长的问题,我深表歉意,但如果你们中的任何人和我一起完成了这个问题,我很乐意就我在这里缺少的东西提出任何建议。这里的最终目标只是创建 QMenu 的派生类(此处为 MyMenu)并将其添加到存在于单独类中的 QMainWindow 派生类(此处为 MainWindow)。感谢您的宝贵时间。

【问题讨论】:

您是否在 mymenu.cpp 中包含 MainWindow.h? 没有。也许这就是问题所在?我向前在 mymenu.h 中声明 MainWindow,希望我可以使菜单类不依赖于 MainWindow 类。这是我第一次向前声明,所以我可能做得不对。 【参考方案1】:

如果 MainWindow 类继承自 QMainWindow,那不是让 'MainWindow' 成为 QObject 吗?

是的,MainWindow QMainWindow QObject(您可以通过浏览 API 文档上的继承树来查看)。

你只有转发声明MainWindow。由于编译器没有类MainWindow 的定义,它只能用指向MainWindow 的指针做最小的事情。为了让编译器“知道”MainWindow 是一个 QMainWindow 是一个 QObject,您必须为MainWindow 提供一个类定义。您可以通过以下方式解决编译器错误:

#include "MainWindow.h"

不需要动态转换

另外,在 Qt 领域中,要使某些东西“真正”成为 QObject,您应该将 Q_OBJECT 宏放在对象上:

class MyMenu : QMenuBar

  Q_OBJECT

public:
    MyMenu(MainWindow *main_window);

;

如果您以后打算将该对象用于信号/插槽或其他 Qt 东西,它可能会为您省去一些麻烦。

在 MainWindow 类中将“this”传递给 QAction 与将“main_window”传递给 QAction 有什么区别? 是(据我所知)也是从内部指向实例的指针 MyMenu 类?

this 是一个指向您的自定义MyMenu 类的指针,也是一个 QMenuBarmain_window 是一个指向您的自定义 MainMenu 类的指针,它也是一个 QMainMenu。所以,内存中有两个不同的对象。 QAction 构造函数的第二个参数接受一个指向父部件的指针。父小部件负责管理其子小部件的内存。由于需要QObject,因此传入thismain_menu 是合理的。


您还应该将父级传递给QMenu 构造函数。

MyMenu::MyMenu(MainWindow *main_window) : QMenuBar(main_window)

这样MyMenuMainWindow被删除时会被正确删除。

通常的 Qt 范式是:

MyMenu::MyMenu(<arg1>, <arg2>, ... QObject * parent) : QMenuBar(parent)

但在这种情况下,沿main_window 转发就足够了。

【讨论】:

非常好的解释,谢谢。不过,对于第二个问题,我试图理解为什么 ZetCode 上的示例可以将“this”传递给 QAction(不需要强制转换),但为什么我不能在没有动态强制转换的情况下通过“main_window”,即使现在我“已将菜单功能移出 MainWindow 类本身。你能帮忙澄清一下吗? 是的。你能告诉我当你尝试通过 main_window 而不进行强制转换时得到什么错误消息吗?这可能只是我不了解的 C++ 的一部分,因此查看错误消息可能会帮助我弄清楚发生了什么。 没有匹配函数调用'QAction::QAction(const char [6], MainWindow*&)' quit = new QAction("&Quit", my_main_window); 这是一个很好的问题,我真的很想找出答案。我会调查的 只是好奇,我正在设置 Qt 构建设置...动态转换是否解决了问题?

以上是关于C++ Qt 派生类的主要内容,如果未能解决你的问题,请参考以下文章

C++类的继承与派生

关于C++基类、派生类的引用和指针

C++派生类用另一个派生类覆盖基类的成员?

C++中的基类和派生类

C++ 派生类访问属性

获取派生类以显示与派生类的父类具有聚合关系的抽象类中的变量的 C++ 错误