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
类的指针,也是一个 QMenuBar
。 main_window
是一个指向您的自定义 MainMenu
类的指针,它也是一个 QMainMenu
。所以,内存中有两个不同的对象。 QAction
构造函数的第二个参数接受一个指向父部件的指针。父小部件负责管理其子小部件的内存。由于需要QObject
,因此传入this
或main_menu
是合理的。
您还应该将父级传递给QMenu
构造函数。
MyMenu::MyMenu(MainWindow *main_window) : QMenuBar(main_window)
这样MyMenu
在MainWindow
被删除时会被正确删除。
通常的 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 派生类的主要内容,如果未能解决你的问题,请参考以下文章