PDA

View Full Version : Returning QPointer via function from one class to another, using the QPointer's data



pditty8811
19th March 2015, 03:21
I've declared a qpointer to a QLineEdit pointer called txtNewCareer in the class Populate. I have created a getter function in Populate so other classes can access that pointer. It is a dynamically created pointer that creates a QLineEdit, which I need to keep as dynamic and on the heap.

So, how do I appropriately call my getter function return_txtNewCareer()? I've had not problems returning regular pointers. But I am just learning how to use QPointers.
As you can see I'm trying to connect a signal of the QPointer txtNewCareer by calling the return_txtNewCareer function of class Populate, to a slot in mainwindow class.

Thanks.
This is a skeleton of my classes with the basic information of what I'm doing.

Populate.h


#include <QPointer>



public:
QLineEdit* return_txtNewCareer();



private:
QPionter<QLineEdit> txtNewCareer;



Populate.cpp


QPointer<QLineEdit> txtNewCareer = new QLineEdit



QLineEdit* Populate::return_txtNewCareer(){
return txtNewCareer;
}


mainwindow.cpp


connect(populate->return_txtNewCareer(), SIGNAL(textEdited(QString)), this, SLOT(txtNewCareer_edited(QString)));


I am unable to get the program to run. I have narrowed down the problem to the connect statement because I have commented it out and the program runs. When I run the program with the connect statement I get this Segmentation fault:



Signal name : SIGSEGV
Signal meaning : Segmentation fault

anda_skoa
19th March 2015, 09:06
Have you checked the result of the getter method?
Is it the pointer you expect?

Cheers,
_

d_stranz
19th March 2015, 16:50
QPointer<QLineEdit> txtNewCareer = new QLineEdit

Although it is impossible to tell from your "one-liner" code posts where this line occurs, if it is indeed as you show it here, it implies you are creating a local QPointer named "txtNewCareer" which is hiding the private member declared in your class definition. As a consequence, your private member is never initialized (i.e. contains a NULL QLineEdit pointer instance) and of course will cause a SEGFAULT when you try to use it.

pditty8811
19th March 2015, 20:56
Although it is impossible to tell from your "one-liner" code posts where this line occurs, if it is indeed as you show it here, it implies you are creating a local QPointer named "txtNewCareer" which is hiding the private member declared in your class definition. As a consequence, your private member is never initialized (i.e. contains a NULL QLineEdit pointer instance) and of course will cause a SEGFAULT when you try to use it.



QPointer<QLineEdit> txtNewCareer = new QLineEdit;

Thanks for the response. How would I initialize it so that it can be access from other classes? Should I make it public? This is often considered bad practice. However, when I change it to public I still get the same problem. So that can't be it.

I understand what you are saying, but if I initialize a non-smart pointer that way it works just fine. But I'd like to use smart pointers to help with garbage clean-up.


Have you checked the result of the getter method?
Is it the pointer you expect?

Cheers,
_

I've tried to use the getter as if it was a non-smart pointer and I can compile but I get segfault during running. And no, the getter does not work as it should.

stampede
19th March 2015, 21:25
How would I initialize it
http://www.learncpp.com/cpp-tutorial/101-constructor-initialization-lists/


Should I make it public?
No, just initialize the class member instead of creating a local object with the same name, as d_stranz already suggested.


But I'd like to use smart pointers to help with garbage clean-up.
QPointer is not managing the cleanup. If you want your object to be automatically deleted when a pointer goes out of scope, use QScopedPointer (http://doc.qt.io/qt-5/qscopedpointer.html)or QSharedPointer (http://doc.qt.io/qt-5/qsharedpointer.html).

d_stranz
20th March 2015, 22:28
However, when I change it to public I still get the same problem. So that can't be it.

As I said before, and as stampede reiterated, if you are doing this:



void SomeClass::someMethod()
{
QPointer<QLineEdit> txtNewCareer = new QLineEdit;

// ...
}

The variable "txtNewCareer" in someMethod() is not the same variable as the one in your class definition. It is a local variable, defined only within the scope of someMethod(). Even if it has the same name as the one in your class definition, it is a different variable and "hides" the one defined in your class. So you are initializing a variable that goes out of scope as soon as the method exits (and creates a memory leak in the process). The variable named txtNewCareer in your class definition is never initialized (except to set it to NULL by the default QPointer constructor), and so when you go to use it, it segfaults.

If you still don't understand this and why what you're doing is wrong, go back to your C++ books and read about scoping.


Should I make it public?

If you really need to get access to the QLineEdit pointer from outside your class, then don't make it a public variable, add a method to safely retrieve the pointer from your class: QPointer< QLineEdit > getLineEdit() const;

But that is nearly as bad an idea as making the variable public, because you have no control over how it is used, and if you change your UI design, everywhere that that pointer is used will have to be changed also. It makes your code fragile. Probably what you actually need is access to the contents of the QLineEdit, not to the widget itself. So in that case, provide getter and setter methods to get or set the QLineEdit text:



QString getText() const
{
return txtNewCareer->text();
}

void setText( const QString & text )
{
txtNewCareer->setText( text );
}


Even if you change the UI to use something instead of a QLineEdit, the rest of your program won't care. The only two lines you'll need to change are the lines that access the QLineEdit from within your getter and setter methods.