Adding a virtual function causes strange result...
-
@SPlatten said in Adding a virtual function causes strange result...:
clsXMLnode::strGetAttribute(QString)
You should check what is happening there
-
@jsulm , this is where its called:
QString clsScriptHelper::getValue(const QString& crstrID) { QString strValue; if ( crstrID.isEmpty() != true ) { clsXMLnode* pobjNode(clsXMLnode::spobjGetNodeById(crstrID)); if ( pobjNode != nullptr ) { clsXMLinterface* pobjXMLif(reinterpret_cast<clsXMLinterface*>(pobjNode)); if ( pobjXMLif != nullptr ) { strValue = pobjXMLif->strGetData(); } } } return strValue; }
The prototype for the above:
Q_INVOKABLE QString getValue(const QString& crstrID);
There is presently only one call to this, the only overridden instance is defined in the class clsQtLineEdit.
Execution stops as I stated on the line I specified in the original post, how can I see if an error or exception has occurred because it isn't obvious.
@SPlatten said in Adding a virtual function causes strange result...:
reinterpret_cast
when using virtual inheritance !?!?!?
use dynamic_cast or if QObject classes object_cast
reinterpret_cast takes the raw pointer and considers it as being of the derived type. However, because of the virtual inheritance, a slight adjustment must be done to the pointer to point to the correct method dispatch table, and that's precisely what dynamic_cast will do.
just as wrong, but probably wouldn't have resulted in a crash would be the use of static_cast.
-
@jsulm , this is where its called:
QString clsScriptHelper::getValue(const QString& crstrID) { QString strValue; if ( crstrID.isEmpty() != true ) { clsXMLnode* pobjNode(clsXMLnode::spobjGetNodeById(crstrID)); if ( pobjNode != nullptr ) { clsXMLinterface* pobjXMLif(reinterpret_cast<clsXMLinterface*>(pobjNode)); if ( pobjXMLif != nullptr ) { strValue = pobjXMLif->strGetData(); } } } return strValue; }
The prototype for the above:
Q_INVOKABLE QString getValue(const QString& crstrID);
There is presently only one call to this, the only overridden instance is defined in the class clsQtLineEdit.
Execution stops as I stated on the line I specified in the original post, how can I see if an error or exception has occurred because it isn't obvious.
This post is deleted! -
@SPlatten said in Adding a virtual function causes strange result...:
reinterpret_cast
when using virtual inheritance !?!?!?
use dynamic_cast or if QObject classes object_cast
reinterpret_cast takes the raw pointer and considers it as being of the derived type. However, because of the virtual inheritance, a slight adjustment must be done to the pointer to point to the correct method dispatch table, and that's precisely what dynamic_cast will do.
just as wrong, but probably wouldn't have resulted in a crash would be the use of static_cast.
@J-Hilk said in Adding a virtual function causes strange result...:
dynamic_cast
I've replaced reinterpret_cast with dynamic_cast, same result.
-
@SPlatten said in Adding a virtual function causes strange result...:
I didn't use the override keyword, should I?
Yes you should. To ask the compiler to check whether you're really overriding virtual method. Can help to detect bugs at compile time.
As I suggested: check what is happening in clsXMLnode::strGetAttribute(QString).
My guess is that the strGetData() method from base class is called which returns an empty string, so the code then fails later. -
@J-Hilk said in Adding a virtual function causes strange result...:
dynamic_cast
I've replaced reinterpret_cast with dynamic_cast, same result.
@SPlatten said in Adding a virtual function causes strange result...:
I've replaced reinterpret_cast with dynamic_cast, same result.
For sure not.
btw: dynamic_cast was proposed to your exact same problem some weeks ago already: https://forum.qt.io/topic/132420/how-to-access/4
-
@SPlatten said in Adding a virtual function causes strange result...:
I didn't use the override keyword, should I?
Yes you should. To ask the compiler to check whether you're really overriding virtual method. Can help to detect bugs at compile time.
As I suggested: check what is happening in clsXMLnode::strGetAttribute(QString).
My guess is that the strGetData() method from base class is called which returns an empty string, so the code then fails later. -
@SPlatten said in Adding a virtual function causes strange result...:
I've replaced reinterpret_cast with dynamic_cast, same result.
For sure not.
btw: dynamic_cast was proposed to your exact same problem some weeks ago already: https://forum.qt.io/topic/132420/how-to-access/4
@Christian-Ehrlicher That issue was resolved, this is new and dynamic_cast wasn't used to resolve the last issue, it was resolved with the suggested qobject_cast.
-
@jsulm, I have a breakpoint on the first line of the function getValue, execution doesn't get as far as the breakpoint before the issue occurs.
-
@jsulm, I have a breakpoint on the first line of the function getValue, execution doesn't get as far as the breakpoint before the issue occurs.
-
@Christian-Ehrlicher That issue was resolved, this is new and dynamic_cast wasn't used to resolve the last issue, it was resolved with the suggested qobject_cast.
@SPlatten said in Adding a virtual function causes strange result...:
it was resolved with the suggested qobject_cast.
Since your class is derived from QObject you can also use qobject_cast. Please learn the basics.
-
@SPlatten said in Adding a virtual function causes strange result...:
it was resolved with the suggested qobject_cast.
Since your class is derived from QObject you can also use qobject_cast. Please learn the basics.
@Christian-Ehrlicher , I find your additions very insulting, I’ve been coding professionally since 1986.
-
@Christian-Ehrlicher , I find your additions very insulting, I’ve been coding professionally since 1986.
@SPlatten
I'm not sure what part of your code you think is implicated. I see:1 QListData::size() const 2 QList<std::pair<QString, QString>>::length() const
and that is failing (according to your "the execution stops in qlist.h on line 115") on trying to get the length of the
QList
. InvalidQList
at that point? That is what I see? -
@Christian-Ehrlicher , I find your additions very insulting, I’ve been coding professionally since 1986.
@SPlatten said in Adding a virtual function causes strange result...:
I’ve been coding professionally since 1986.
But not with c++ (at least I hope so) - when I want to learn a new language I normally start to learn the basics. But you ignore those basics in nearly every 'problem' you have and then wonder why people complain about the lack of the basics.
-
@SPlatten said in Adding a virtual function causes strange result...:
I’ve been coding professionally since 1986.
But not with c++ (at least I hope so) - when I want to learn a new language I normally start to learn the basics. But you ignore those basics in nearly every 'problem' you have and then wonder why people complain about the lack of the basics.
@Christian-Ehrlicher that’s a huge assumption on your part.
-
@SPlatten your stack trace actually points to your
clsXMLnode
class.
clsXMLnode::strGetAttribute@J-Hilk said in Adding a virtual function causes strange result...:
@SPlatten your stack trace actually points to your clsXMLnode class.
clsXMLnode::strGetAttributeIf he
reinterpret_cast
s it's going to point to that class and method since that's what to "reinterpret" means.@SPlatten said in Adding a virtual function causes strange result...:
I've replaced reinterpret_cast with dynamic_cast, same result.
You shouldn't use
reinterpret_cast
to begin with, as it's rather apparent you don't understand the implications of it; specifically to polymorphic calls and multiple inheritance. So while @Christian-Ehrlicher may seem brusque, you should do yourself a favor and listen to the advice.As for the issue at hand, you have called
strGetAttribute
on an invalid object, I'm reasonably certain. The reasons may vary, andreinterpret_cast
ing incompatible types is one. Dangling pointers and uninitialized memory are other candidates. You need to sift through the debugger to find it. Out of curiosity where doesclsQtLayout::addButton
callclsXMLnode::strGetAttribute
and where doesclsXMLnode::setWidget
callclsQtLayout::addButton
- provide the relevant code around the calls. -
@J-Hilk said in Adding a virtual function causes strange result...:
@SPlatten your stack trace actually points to your clsXMLnode class.
clsXMLnode::strGetAttributeIf he
reinterpret_cast
s it's going to point to that class and method since that's what to "reinterpret" means.@SPlatten said in Adding a virtual function causes strange result...:
I've replaced reinterpret_cast with dynamic_cast, same result.
You shouldn't use
reinterpret_cast
to begin with, as it's rather apparent you don't understand the implications of it; specifically to polymorphic calls and multiple inheritance. So while @Christian-Ehrlicher may seem brusque, you should do yourself a favor and listen to the advice.As for the issue at hand, you have called
strGetAttribute
on an invalid object, I'm reasonably certain. The reasons may vary, andreinterpret_cast
ing incompatible types is one. Dangling pointers and uninitialized memory are other candidates. You need to sift through the debugger to find it. Out of curiosity where doesclsQtLayout::addButton
callclsXMLnode::strGetAttribute
and where doesclsXMLnode::setWidget
callclsQtLayout::addButton
- provide the relevant code around the calls.@kshegunov , using the debugger I have a break point on the last if condition below:
clsXMLinterface* pobjInterface(reinterpret_cast<clsXMLinterface*>(pobjButton)); clsXMLnode* pobjNode(nullptr); if ( pobjInterface != nullptr ) { pobjNode = pobjInterface->pobjGetNode(); } if ( pobjNode == nullptr ) { return; }
pobjButton is a pointer to an instance of my derived class clsQtRadioButton:
class clsQtRadioButton : public QRadioButton, public clsXMLinterface { Q_OBJECT
pobjNode is returned as not null, pobjGetNode:
clsXMLnode* pobjGetNode() { return mpobjNode; }
I can see in the debugger the pobjInterface looks ok and mpobjNode is correct as I have assigned a human readable description to it:
However pobjNode doesn't appear to be correct:
And then trying to call strGetAttribute fails and causes the problem, but its because pobjNode isn't correct, why ?
If I change the code to:clsQtRadioButton* pobjRadioBtn(qobject_cast<clsQtRadioButton*>(pobjButton)); clsXMLnode* pobjNode(pobjRadioBtn->pobjGetNode());
This way pobjNode is valid and there is no problem, however I need a polymorphic way to access pobjGetNode because there can be lots of different types of object derived from the same base class and I need the functionality to work for all of them.
-
@kshegunov , using the debugger I have a break point on the last if condition below:
clsXMLinterface* pobjInterface(reinterpret_cast<clsXMLinterface*>(pobjButton)); clsXMLnode* pobjNode(nullptr); if ( pobjInterface != nullptr ) { pobjNode = pobjInterface->pobjGetNode(); } if ( pobjNode == nullptr ) { return; }
pobjButton is a pointer to an instance of my derived class clsQtRadioButton:
class clsQtRadioButton : public QRadioButton, public clsXMLinterface { Q_OBJECT
pobjNode is returned as not null, pobjGetNode:
clsXMLnode* pobjGetNode() { return mpobjNode; }
I can see in the debugger the pobjInterface looks ok and mpobjNode is correct as I have assigned a human readable description to it:
However pobjNode doesn't appear to be correct:
And then trying to call strGetAttribute fails and causes the problem, but its because pobjNode isn't correct, why ?
If I change the code to:clsQtRadioButton* pobjRadioBtn(qobject_cast<clsQtRadioButton*>(pobjButton)); clsXMLnode* pobjNode(pobjRadioBtn->pobjGetNode());
This way pobjNode is valid and there is no problem, however I need a polymorphic way to access pobjGetNode because there can be lots of different types of object derived from the same base class and I need the functionality to work for all of them.
@SPlatten said in Adding a virtual function causes strange result...:
why ?
We do not know whether and how you're initialising it...
"pobjNode is returned as not null" - doesn't mean it was initialised. You should initialise your pointers with nullptr before they are assigned proper pointers, else they can contain garbage.
-
@SPlatten said in Adding a virtual function causes strange result...:
why ?
We do not know whether and how you're initialising it...
"pobjNode is returned as not null" - doesn't mean it was initialised. You should initialise your pointers with nullptr before they are assigned proper pointers, else they can contain garbage.
@jsulm , here is the constructor for the class clsXMLinterface:
clsXMLinterface::clsXMLinterface(clsXMLnode* pobjNode) : mpobjNode(pobjNode) {
And clsQtRadioButton:
clsQtRadioButton::clsQtRadioButton(clsXMLnode* pobjNode, QString* pstrCSS , QWidget* pParent) : QRadioButton(pParent), clsXMLinterface(pobjNode) {
The formatting of this constructor is common to all instances. Widgets like instances of clsQtRadioButton are created by another call:
pobjWidget = qobject_cast<QWidget*>(clsCNT::pCreate(this, mstrName, strCSS, slstProperties, pobjParWidget));
clsCNT::pCreate:
QWidget* clsCNT::pCreate(clsXMLnode* pobjNode, const QString& crstrType ,QString& rstrCSS, QStringList& rslstProperties ,QWidget* pobjParent) { QWidget* pobjWidget(nullptr); if ( pobjNode != nullptr ) { if ( crstrType.compare(clsCNT::mscszButton) == 0 ) { pobjWidget = new clsQtPushBtn(pobjNode, &rstrCSS, pobjParent);
The above is just a sample, pobjNode is passed by pCreate as this.
-
@jsulm , here is the constructor for the class clsXMLinterface:
clsXMLinterface::clsXMLinterface(clsXMLnode* pobjNode) : mpobjNode(pobjNode) {
And clsQtRadioButton:
clsQtRadioButton::clsQtRadioButton(clsXMLnode* pobjNode, QString* pstrCSS , QWidget* pParent) : QRadioButton(pParent), clsXMLinterface(pobjNode) {
The formatting of this constructor is common to all instances. Widgets like instances of clsQtRadioButton are created by another call:
pobjWidget = qobject_cast<QWidget*>(clsCNT::pCreate(this, mstrName, strCSS, slstProperties, pobjParWidget));
clsCNT::pCreate:
QWidget* clsCNT::pCreate(clsXMLnode* pobjNode, const QString& crstrType ,QString& rstrCSS, QStringList& rslstProperties ,QWidget* pobjParent) { QWidget* pobjWidget(nullptr); if ( pobjNode != nullptr ) { if ( crstrType.compare(clsCNT::mscszButton) == 0 ) { pobjWidget = new clsQtPushBtn(pobjNode, &rstrCSS, pobjParent);
The above is just a sample, pobjNode is passed by pCreate as this.
This post is deleted!