PDA

View Full Version : Error accessing pointer to class member in main



starkid
15th October 2011, 16:37
In a subclass of QMainWindow, I have created a pointer to a QPushButton:


class appWindow : public QMainWindow
{
Q_OBJECT

public:
appWindow();
QPushButton *quit;


I am trying to use this button to exit the application in main.cpp:



int main(int argc, char *argv[])
{
QApplication VocabAide(argc, argv);
appWindow mainWindow; //instance of class appWindow

QObject::connect(mainWindow.*quit, SIGNAL(clicked()), &VocabAide, SLOT(quit()));


appwindow.h is included in main.cpp. I am receiving a single error: ‘quit’ was not declared in this scope.

I'm wondering if the problem has to do with class instance mainWindow not being a child of the QApplication. I don't understand how QApplication fits (or how I make it fit) into the parent-child hierarchy since it doesn't derive from QObject.

mvuori
15th October 2011, 17:40
How about mainWindow->quit...

(You need to brush up your C++ skills... Have you ever seen a ".*" reference anywhere?)

starkid
15th October 2011, 18:07
I've tried mainWindow->quit already. I get the error:

base operand of ‘->’ has non-pointer type ‘appWindow’

My understanding is that the object->member construction only works in the case in which the object is a pointer, which mainWindow is not.

I got .* from http://www.oopweb.com/CPP/Documents/CPPAnnotations/Volume/cplusplus15.html:

"To use a pointer to a member in combination with an object the pointer to member field selector ( .*) must be used."

Zlatomir
15th October 2011, 18:31
Just

connect(mainWindow.quit, //...
should do the trick. //you don't need to deference the quit pointer, since the connection takes pointers as parameters.

And don't forget to take and pass a parent to the QMainWindow's constructor. //just to avoid future problems like memory leak/object slicing.

starkid
15th October 2011, 18:34
Just

And don't forget to take and pass a parent to the QMainWindow's constructor. //just to avoid future problems like memory leak/object slicing.

How does that work? QMainWidget can take a QWidget as a parent, but QApplication is not derived from QWidget. Is it necessary to create an intermediate widget in main to pass as a parent?

Also, there is still a problem. I'm getting:

error: no matching function for call to ‘QObject::connect(QPushButton*&, const char [11], QApplication*, const char [8])

The first argument, QPushButton*&, looks like a problem with mainWindow.quit.

Zlatomir
15th October 2011, 18:40
No, you don't need an "intermediary" widget, you pass 0 (NULL), the only thing is that you are responsible to delete the widgets that don't get a parent (or get that NULL) so that you trigger the proper deletion of it's children widgets, this can be done either by allocating the "mainWindow" on the stack in the main function or call delete if you allocated it on stack.

LE: Full example code:


#include <QApplication>
#include <QMainWindow>
#include <QPushButton>

class appWindow : public QMainWindow
{
Q_OBJECT
public:
appWindow(QWidget* parent = 0);
QPushButton *quit;
};

appWindow::appWindow(QWidget* parent) : QMainWindow(parent)
{
quit = new QPushButton("quit", this);
}

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

appWindow w;
QObject::connect(w.quit, SIGNAL(clicked()), &app, SLOT(quit()));
w.show();

return app.exec();
}

#include "main.moc"

starkid
15th October 2011, 19:11
the only thing is that you are responsible to delete the widgets that don't get a parent (or get that NULL)


I don't understand how passing NULL prevents memory leak if I have to delete the object to which it is passed. Wouldn't I also have to delete it explicitly if I passed nothing at all?

Zlatomir
15th October 2011, 19:13
I don't understand how passing NULL prevents memory leak if I have to delete the object to which it is passed. Wouldn't I also have to delete it explicitly if I passed nothing at all?
If you pass nothing (pass the default NULL) and your widget doesn't get a parent (by for example if you add your widget into a layout) you need to delete your widget, i out case it is deleted because it is allocated on stack.

If you allocate it on the heap you do something like:


int main(int argc, char *argv[])
{
QApplication app(argc, argv);

appWindow *w = new appWindow(); //default parent is null, so our widget doesn't have a parent
QObject::connect(w->quit, SIGNAL(clicked()), &app, SLOT(quit())); //use the arrow
w->show();

int ret_value = app.exec(); //hold the value returned by QApplication exec
delete w; //delete the widget, this line will trigger the deletion of the quit pointer (because it is a child of your widget)
return ret_value; //return the value...
}

starkid
15th October 2011, 19:23
Thanks for the full example. I forgot to include QPushButton in main.cpp. Works fine now.