c++ - 如何让低级类调用其父类的方法?
问题描述
我遵循了这个 turorial Qt Creator + OpenGL并且一切顺利。
我QPlainTextEdit
在按钮顶部添加了一个Quit
,我希望GLWidget
将信息发送回MainWindow
。
我怎样才能使GLWidget
call 的功能MainWindow
?
这是一些代码:
// GLWidget.h
class GLWidget: public QGLWidget
{
Q_OBJECT // <-----
public:
GLWidget(QWidget* parent = 0);
QWidget* parentObject;
void writeText( QString );
void (*p)(QString) = NULL;
protected:
virtual void initializeGL();
virtual void paintGL();
virtual void resizeGL(int w, int h);
private:
QTimer timer;
signals:
//void writeText( QString );
void dataReady(QString data); // <------------------
};
// GLWidget.cpp
GLWidget::GLWidget(QWidget* parent) : QGLWidget() /7 <---- new error
{
connect(&timer, SIGNAL(timeout()), this, SLOT(updateGL()));
timer.start(16);
QMessageBox msgBox;
msgBox.setText(typeid(parent).name());
msgBox.exec();
//p = parent->
//parentObject->
//parent->
//parent->
//this->parentObject = parent;
}
void GLWidget::initializeGL(){
//emit GLWidget::dataReady("myData"); //<--------- error
emit this->dataReady("Joe");//<--------- same as above
glClearColor(0.2, 0.2, 0.2, 1);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
}
// MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void print(QString text);
private slots:
void on_plainTextEdit_textChanged();
void foo(QString data); // <----------------------
}
// 主窗口.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->widget->p = &MainWindow::print; // error, how to asign pointer?
}
void MainWindow::print(QString text){
ui->plainTextEdit->setPlainText(text);
}
void MainWindow::foo(QString data) { // <---------
QMessageBox msgBox;
msgBox.setText("hi, there");
msgBox.exec();
// Do something with the data
ui->plainTextEdit->setPlainText(data);
}
错误:
- 未定义对“GLWidget 的vtable”的引用
- 未定义对 `GLWidget::dataReady(QString)' 的引用
解决方案
这是您直接问题的答案,如何使低级类利用其父级中的功能?:
所有QObject
子类都持有对其父对象的引用,可通过该parent()
方法访问。
- 包括父类的标题,例如
Foo.h
- 调用
parent()
方法获取指向对象父级的指针 - 检查指针是否有效(不是 a
nullptr
) - 将指针转换为父类,例如
Foo
- 调用所需的方法,例如
foo
在代码中它看起来像这样:
#include "Foo.h"
...
if (parent())
static_cast<Foo *>(parent())->foo();
话虽如此,这会在父母和孩子之间造成紧密的耦合,我强烈建议尽可能避免这样做。在您的情况下,使用信号和插槽将数据从子级传递给父级会更好:
- 在孩子中定义一个信号,例如
dataReady(DataType data)
- 在父级中,当您创建子级时,将此信号连接到将使用数据的方法,例如
foo
- 在孩子身上,
emit
信号,每当你想打电话时foo
在代码中它看起来像这样:
孩子.h
...
signals:
void dataReady(DataType data);
...
孩子.cpp
...
// I want to call foo
emt dataReady(myData);
...
父.h
...
private slots:
void foo(DataType data);
...
父级.cpp
...
//somewhere
auto *child = new Child(...);
connect(child, &Child::dataReady, this, &Parent::foo);
...
void Parent::foo(DataType data) {
// Do something with the data
...
}
...
这最初需要更多的工作,但从长远来看会好得多。
推荐阅读
- aws-lambda - AWS Lambda 通过 PG.js 连接到 RDS Postgres 数据库(已建立连接,没有超时,但没有数据库?)
- angular - 角 | 打字稿 | 数据表不分页/排序
- c# - `RequestPermissionAsync` 没有返回,也没有按预期工作。Ask Permission wait for it and GetLocation when permission is allowed 问题
- google-app-engine - 没有可用于谷歌云任务的日志?
- raku - 日志类参考
- flutter - How to save values selected from a flutter multiselect widget in to a list
- reactjs - 在 React Native 中,如何在状态更改时更改导航选项?
- selenium - 黄瓜示例表未正确分隔
- ssms - 使用 SSMS 2014,如何生成高效的插入脚本?
- azure - 如何在 MS Azure 中创建应用程序以使用 aws lex 在 Outlook Office 365 中安排约会