PDA

View Full Version : subclassing MainForm class



mickey
4th March 2006, 11:56
Hi,
I'm subclassing MainForm class (create from qtDesigner). I code insert new mymainform.cpp e mymainform.h. and seems ok. But when I create an instance of it in main.cpp, linker get these errors:


Editor error LNK2001: unresolved external symbol "public: virtual bool __thiscall myMainForm::qt_emit(int,struct QUObject *)" (?qt_emit@myMainForm@@UAE_NHPAUQUObject@@@Z)
Editor error LNK2001: unresolved external symbol "public: virtual bool __thiscall myMainForm::qt_invoke(int,struct QUObject *)" (?qt_invoke@myMainForm@@UAE_NHPAUQUObject@@@Z)
Editor error LNK2001: unresolved external symbol "public: virtual bool __thiscall myMainForm::qt_property(int,int,class QVariant *)" (?qt_property@myMainForm@@UAE_NHHPAVQVariant@@@Z)
Editor error LNK2001: unresolved external symbol "public: virtual char const * __thiscall myMainForm::className(void)const " (?className@myMainForm@@UBEPBDXZ)
Editor error LNK2001: unresolved external symbol "public: virtual void * __thiscall myMainForm::qt_cast(char const *)" (?qt_cast@myMainForm@@UAEPAXPBD@Z)
Editor error LNK2019: unresolved external symbol "public: static class QMetaObject * __cdecl myMainForm::staticMetaObject(void)" (?staticMetaObject@myMainForm@@SAPAVQMetaObject@@X Z) referenced in function "public: virtual class QMetaObject * __thiscall myMainForm::metaObject(void)const " (?metaObject@myMainForm@@UBEPAVQMetaObject@@XZ)
Editor fatal error LNK1120: 6 unresolved externals



//mymainform.h
#include "mainform.h"
#include "mywidget.h"
class myMainForm : public MainForm
{
Q_OBJECT

public:
myMainForm( QWidget* parent = 0, const char* name = 0, WFlags fl = WType_TopLevel );
~myMainForm();
MyWidget top;
};


//mymainform.cpp
#include "mymainform.h"
myMainForm::myMainForm( QWidget* parent, const char* name, WFlags fl )
: MainForm( parent, name, fl )
{
}

myMainForm::~myMainForm()
{
}


//main.cpp
#include "mymainform.h"
..........
//MainForm w;
myMainForm w;
w.resize(600,500);
a.setMainWidget(&w);
w.show();
a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
return a.exec();
What happen?

jacek
4th March 2006, 11:58
Did you rerun qmake after you have added Q_OBJECT to myMainForm class?

mickey
4th March 2006, 14:33
No, but there are still errors (after nmake clean;qmake;nmake)


LINK : warning LNK4199: /DELAYLOAD:comdlg32.dll ignored; no imports found from comdlg32.dll
LINK : warning LNK4199: /DELAYLOAD:oleaut32.dll ignored; no imports found from oleaut32.dll
LINK : warning LNK4199: /DELAYLOAD:winmm.dll ignored; no imports found from winmm.dll
LINK : warning LNK4199: /DELAYLOAD:wsock32.dll ignored; no imports found from wsock32.dll
LINK : warning LNK4199: /DELAYLOAD:winspool.dll ignored; no imports found from winspool.dll
main.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall myMainForm::~myMainForm(void)" (??1myMainForm@@UAE@XZ) referenced in
function _main
main.obj : error LNK2019: unresolved external symbol "public: __thiscall myMainForm::myMainForm(class QWidget *,char const *,unsigned int)" (??0myMain
Form@@QAE@PAVQWidget@@PBDI@Z) referenced in function _main
Editor.exe : fatal error LNK1120: 2 unresolved externals
NMAKE : fatal error U1077: 'link' : return code '0x460'
Stop.

wysota
4th March 2006, 14:39
Check if you have mymainform.cpp mentioned in SOURCES section of your project file. Add it if it's not there and rerun qmake afterwards.

mickey
4th March 2006, 14:48
Thanks you; yes it was .pro

//mywidget.cpp


connect(this, SIGNAL(myUpdate()), w ,SLOT(updateWidgets()) );

w is MainForm* w; and updateWidget() a SLOT in MainForm class...

appear a message saying: "no such SLOT" sender and receiver unamed"

This is the first time I subclassing MainForm created fom QTDesigner. I change only the code You see above and seems works properly! Are there to doother changes?
Thanks

mickey
4th March 2006, 15:28
I resolve it changing MyWidget declaration to pointer (below coded)


class myMainForm : public MainForm
{
Q_OBJECT

public:
myMainForm( QWidget* parent = 0, const char* name = 0, WFlags fl = WType_TopLevel );
~myMainForm();
void init();
//MyWidget top
MyWidget* top;
};
But now my problem don't chage. I do it for to do this:

myMainForm::myMainForm( QWidget* parent, const char* name, WFlags fl )
: MainForm( parent, name, fl )
{
printf("myMainformt\n");
*top = MyWidget(this, "top shared", this->myWidget1);
this->WidgetStack->addWidget(top);
}
This two istruction cause some 'debug error' when I launch app....
The same if I code these two in main.cpp

mickey
5th March 2006, 16:47
Nothing hints for this last problem, please?

jacek
5th March 2006, 17:11
*top = MyWidget(this, "top shared", this->myWidget1);
You can't copy widgets --- try:
top = new MyWidget(this, "top shared", this->myWidget1);

mickey
5th March 2006, 21:15
It seems ok;
I have a problem. In mywidget.cpp constructor I have:

connect(this, SIGNAL(myUpdate()), w, SLOT(myUpdateWidgets()) );
in main.cpp:

myMainForm w; a.setMainWidget(&w);....
When I launch app appear this message:


QObject::connect: No such slot MainForm::myUpdateWidgets()
QObject::connect: (sender name: 'myWidget1')
QObject::connect: (receiver name: 'MainForm')

myUpdateWidgets() is a SLOT of myMainForm! And not MainForm (base class)
Why doesn't it work? Thanks

jacek
5th March 2006, 21:37
How did you declare that slot? Could you also post the .pro file?

mickey
5th March 2006, 23:54
Hi, the error message above is at runtime (in console).
I saw now the problem is in other place...


//myWidget.h
class MyWidget {
MainForm* w;
}
When I use in costructor of MyWidget: "connect(this, SIGNAL(myUpdate()), w, SLOT(myUpdateWidgets()) );" w pointer refers to MainForm;
But if I change in 'myMainForm* w' (in mywidget.h), compiler says me 'class redefinition error....' (error refers to line "class myMainForm {...." in mymainform.h)
I need a pointer to myMainForm class from MyWidget class (as It was for MainForm..)
Thanks

jacek
6th March 2006, 00:18
But if I change in 'myMainForm* w' (in mywidget.h), compiler says me 'class redefinition error....' (error refers to line "class myMainForm {...." in mymainform.h)
Could you at least learn to post exact error messages?


I need a pointer to myMainForm class from MyWidget class (as It was for MainForm..)
If you need that pointer only to make the connection, then make this connection in a different place (where you have both pointers).

mickey
6th March 2006, 11:32
Thanks. The error is:

mymainform.h(4): error C2011: 'myMainForm' : 'class' type redefinition
I need to obtain his pointer here.
I don't undertand why for MainForm there aren't problems (I declareed pointer to myMainForm in the same way of pointer to MainForm:


//mywidget.h
class MyWidget {
MainForm* w;
myMainForm* myw;
}

jacek
6th March 2006, 14:58
mymainform.h(4): error C2011: 'myMainForm' : 'class' type redefinition
What do you have in 4th line of the mymainform.h class?

Did you guard all your headers using following code?
#ifndef __FILE_NAME_H__
#define __FILE_NAME_H__
...
#endif // __FILE_NAME_H__

mickey
6th March 2006, 17:45
Now compile successful.
the line 4 is:

class myMainForm : public MainForm
in mywidget.h I have #include "mymainform.h"
in mymainform.h I have #include "mywidget.h"
Is it a cycle!? Is this the cause?
Thanks

jacek
6th March 2006, 19:00
in mywidget.h I have #include "mymainform.h"
in mymainform.h I have #include "mywidget.h"
Is it a cycle!?
Yes, it is. You can avoid it using forward declaration.

mickey
6th March 2006, 20:09
sorry,
what does 'forward declarations' mean?

jpn
6th March 2006, 20:15
sorry,
what does 'forward declarations' mean?
Ever tried google (http://www.google.fi/search?q=c%2B%2B+forward+declaration)? ;)

mickey
6th March 2006, 20:39
Hi I tried this and work!


#ifndef MYMAINFORM_H
#define MYMAINFORM_H
//#include "mywidget.h"
class MyWidget;

class myMainForm : public MainForm
{
Q_OBJECT

public:
myMainForm( QWidget* parent = 0, const char* name = 0, WFlags fl = WType_TopLevel );
~myMainForm();
MyWidget* myWidget2;
MyWidget* myWidget3;

public slots:
void myChangeView(QAction* action);
signals:
void myMainFormUpdate();
};
#endif
A Question: to toggle include "mywidget.h" I needed to insert #include "mywidget.h" inside mymainform.cpp. Wasn't it the same? Why is better of my previus code (apart avoid cycle problem).
Thanks

jpn
6th March 2006, 20:55
A Question: to toggle include "mywidget.h" I needed to insert #include "mywidget.h" inside mymainform.cpp. Wasn't it the same? Why is better of my previus code (apart avoid cycle problem).
Thanks

You should use forward declarations whenever possible. Use includes only when forward declaration is not suitable.

Forward declaration is adequate for pointers and references. You have to use includes when compiler needs to know the size of a type. This is the case when you inherit from a class or you have an aggregate object as a class member variable.

By filling your header files with unnecessary includes only generates extra dependencies and slows compiling down for no purpose at all.