Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 5

Qt-interest Archive, March 2002
AW: Linker error in VS 6.0 - the code


Message 1 in thread

Okay, I'm now posting the code of the two project files:

aboutdialog.h:

#include <qwidget.h>
#include <qmultilineedit.h>
#include <qpushbutton.h>
#include <qlayout.h>

class CAboutDialog : public QWidget
{
	Q_OBJECT
public:
	CAboutDialog(QWidget *parent = 0, const char *name = 0, WFlags f = 0
);

private:
	QMultiLineEdit *info;
};

CAboutDialog::CAboutDialog(QWidget *parent, const char *name, WFlags
f):QWidget(parent,name,f)
{
	//setFixedSize(200,250); //x,y of window
	
	//Widgets erzeugen
	info = new QMultiLineEdit (this);
	info->setGeometry (10,10,180,200);
	QPushButton *okay = new QPushButton ("OK",this,"okay");

	//Layout erzeugen und aktivieren (anzeigen)
	QVBoxLayout *infoLayout = new QVBoxLayout (this,10);
	QHBoxLayout *buttonLayout = new QHBoxLayout ();
	infoLayout->addWidget(info);
    infoLayout->addLayout(buttonLayout);
	buttonLayout->addWidget(okay);
	infoLayout->activate();

	//Eigenschfaten festlegen
	connect(okay,SIGNAL(clicked()),this,SLOT(quit()));
	info->setReadOnly(TRUE);
	this->setCaption("About");
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''
main.cpp:

#include <qapplication.h>
#include "aboutdialog.h"


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

	CAboutDialog d;
	//app.setMainWidget(&dialog);

	d.show();

	return app.exec();
}

Hope that gives you more information...

Björn

> -----Ursprüngliche Nachricht-----
> Von: Soeren.Fietzke@t-online.de [mailto:Soeren.Fietzke@t-online.de]
> Gesendet: Dienstag, 12. März 2002 15:56
> An: Berg, Björn; QT Mailing List (E-Mail)
> Betreff: Re: Linker error in VS 6.0
> 
> 
> No, no, don't do that :-)
> On second thought, the constructor of CAboutDialog should not 
> appear in the moc file at all.
> If the code is not too long, perhaps just post it?
> 
> - Soeren
> 
> 
> ----- Original Message -----
> From: "Berg, Björn" <BERG@genesys-e.de>
> To: <Soeren.Fietzke@t-online.de>; "QT Mailing List (E-Mail)" 
> <qt-interest@trolltech.com>
> Sent: Tuesday, March 12, 2002 3:50 PM
> Subject: AW: Linker error in VS 6.0
> 
> 
> No, I do not include "moc_aboutdialog.cpp" in main.cpp... Is this
> necessary??
> 
> Björn
> 
> 


Message 2 in thread

OK... now it's obvious.
Either declare 'CAboutDialog::CAboutDialog(QWidget *parent, const char
*name, WFlags f)' inline or put the implementation directly into the class
declaration or, what's probably the most elegant solution, put it inzo a
separate .cpp file. Then it should link properly.

Tom


-----Ursprüngliche Nachricht-----
Von: "Berg, Björn" [mailto:BERG@genesys-e.de]
Gesendet: Dienstag, 12. März 2002 16:04
An: 'Soeren.Fietzke@t-online.de'; QT Mailing List (E-Mail)
Betreff: AW: Linker error in VS 6.0 - the code


Okay, I'm now posting the code of the two project files:

aboutdialog.h:

#include <qwidget.h>
#include <qmultilineedit.h>
#include <qpushbutton.h>
#include <qlayout.h>

class CAboutDialog : public QWidget
{
	Q_OBJECT
public:
	CAboutDialog(QWidget *parent = 0, const char *name = 0, WFlags f = 0
);

private:
	QMultiLineEdit *info;
};

CAboutDialog::CAboutDialog(QWidget *parent, const char *name, WFlags
f):QWidget(parent,name,f)
{
	//setFixedSize(200,250); //x,y of window
	
	//Widgets erzeugen
	info = new QMultiLineEdit (this);
	info->setGeometry (10,10,180,200);
	QPushButton *okay = new QPushButton ("OK",this,"okay");

	//Layout erzeugen und aktivieren (anzeigen)
	QVBoxLayout *infoLayout = new QVBoxLayout (this,10);
	QHBoxLayout *buttonLayout = new QHBoxLayout ();
	infoLayout->addWidget(info);
    infoLayout->addLayout(buttonLayout);
	buttonLayout->addWidget(okay);
	infoLayout->activate();

	//Eigenschfaten festlegen
	connect(okay,SIGNAL(clicked()),this,SLOT(quit()));
	info->setReadOnly(TRUE);
	this->setCaption("About");
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''
main.cpp:

#include <qapplication.h>
#include "aboutdialog.h"


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

	CAboutDialog d;
	//app.setMainWidget(&dialog);

	d.show();

	return app.exec();
}

Hope that gives you more information...

Björn

> -----Ursprüngliche Nachricht-----
> Von: Soeren.Fietzke@t-online.de [mailto:Soeren.Fietzke@t-online.de]
> Gesendet: Dienstag, 12. März 2002 15:56
> An: Berg, Björn; QT Mailing List (E-Mail)
> Betreff: Re: Linker error in VS 6.0
> 
> 
> No, no, don't do that :-)
> On second thought, the constructor of CAboutDialog should not 
> appear in the moc file at all.
> If the code is not too long, perhaps just post it?
> 
> - Soeren
> 
> 
> ----- Original Message -----
> From: "Berg, Björn" <BERG@genesys-e.de>
> To: <Soeren.Fietzke@t-online.de>; "QT Mailing List (E-Mail)" 
> <qt-interest@trolltech.com>
> Sent: Tuesday, March 12, 2002 3:50 PM
> Subject: AW: Linker error in VS 6.0
> 
> 
> No, I do not include "moc_aboutdialog.cpp" in main.cpp... Is this
> necessary??
> 
> Björn
> 
> 

--
 [ signature omitted ] 

Message 3 in thread

Bjorn,
I get the same link problems with the projects that I bring over from
Linux to Windows.  I did a search on Trolltech's site and found a
solution that gives a working executable.  When you run qmake on you
.pro file, it produces a Makefile.  If you look in the Makefile you will
see a line that says:
  LINK	=	link
If you change it to the following: 
  LINK	=	link /FORCE:mulitple

It will build a working executable for you, although it still gives you
a bunch of link warnings and notifies you that the only reason it is
linking is because you put the FORCE command in.  I'm still kind of
scared of it as a solution, but it seems to work in my case.

Tom,
Could you explain more about why your solution needs to be done?  Does
Visual C++ have a problem when things aren't defined in the class
declaration or something?  If so, what types of function definitions
need to be done in the class definition?  In my projects, I always
declare my class functions in the .h file, then define the functions in
the .cpp file (which I thought is the "right way" for C++), but I'd
really like to get rid of these linker errors.

Sean



-----Original Message-----
From: owner-qt-interest@trolltech.com
[mailto:owner-qt-interest@trolltech.com] On Behalf Of Bauer Thomas
Sent: Tuesday, March 12, 2002 10:20 AM
To: 'BERG@genesys-e.de'; 'Soeren.Fietzke@t-online.de'; QT Mailing List
(E-Mail)
Subject: AW: Linker error in VS 6.0 - the code


OK... now it's obvious.
Either declare 'CAboutDialog::CAboutDialog(QWidget *parent, const char
*name, WFlags f)' inline or put the implementation directly into the
class declaration or, what's probably the most elegant solution, put it
inzo a separate .cpp file. Then it should link properly.

Tom


-----Ursprüngliche Nachricht-----
Von: "Berg, Björn" [mailto:BERG@genesys-e.de]
Gesendet: Dienstag, 12. März 2002 16:04
An: 'Soeren.Fietzke@t-online.de'; QT Mailing List (E-Mail)
Betreff: AW: Linker error in VS 6.0 - the code


Okay, I'm now posting the code of the two project files:

aboutdialog.h:

#include <qwidget.h>
#include <qmultilineedit.h>
#include <qpushbutton.h>
#include <qlayout.h>

class CAboutDialog : public QWidget
{
	Q_OBJECT
public:
	CAboutDialog(QWidget *parent = 0, const char *name = 0, WFlags f
= 0 );

private:
	QMultiLineEdit *info;
};

CAboutDialog::CAboutDialog(QWidget *parent, const char *name, WFlags
f):QWidget(parent,name,f)
{
	//setFixedSize(200,250); //x,y of window
	
	//Widgets erzeugen
	info = new QMultiLineEdit (this);
	info->setGeometry (10,10,180,200);
	QPushButton *okay = new QPushButton ("OK",this,"okay");

	//Layout erzeugen und aktivieren (anzeigen)
	QVBoxLayout *infoLayout = new QVBoxLayout (this,10);
	QHBoxLayout *buttonLayout = new QHBoxLayout ();
	infoLayout->addWidget(info);
    infoLayout->addLayout(buttonLayout);
	buttonLayout->addWidget(okay);
	infoLayout->activate();

	//Eigenschfaten festlegen
	connect(okay,SIGNAL(clicked()),this,SLOT(quit()));
	info->setReadOnly(TRUE);
	this->setCaption("About");
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''
main.cpp:

#include <qapplication.h>
#include "aboutdialog.h"


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

	CAboutDialog d;
	//app.setMainWidget(&dialog);

	d.show();

	return app.exec();
}

Hope that gives you more information...

Björn

> -----Ursprüngliche Nachricht-----
> Von: Soeren.Fietzke@t-online.de [mailto:Soeren.Fietzke@t-online.de]
> Gesendet: Dienstag, 12. März 2002 15:56
> An: Berg, Björn; QT Mailing List (E-Mail)
> Betreff: Re: Linker error in VS 6.0
> 
> 
> No, no, don't do that :-)
> On second thought, the constructor of CAboutDialog should not
> appear in the moc file at all.
> If the code is not too long, perhaps just post it?
> 
> - Soeren
> 
> 
> ----- Original Message -----
> From: "Berg, Björn" <BERG@genesys-e.de>
> To: <Soeren.Fietzke@t-online.de>; "QT Mailing List (E-Mail)"
> <qt-interest@trolltech.com>
> Sent: Tuesday, March 12, 2002 3:50 PM
> Subject: AW: Linker error in VS 6.0
> 
> 
> No, I do not include "moc_aboutdialog.cpp" in main.cpp... Is this 
> necessary??
> 
> Björn
> 
> 

--
 [ signature omitted ] 

Message 4 in thread

I could have probably told you that earlier without knowing the code but,
shame on me, I hadn't read the linker error message carefully.

Tom


Message 5 in thread

Only for testing I have done what you said, but the error is already there.
For me it is very hard to understand why I should create an extra file for
implementation or a direct implementation in the class. Normal C++ works
with implementation outside the class best and it  is the same with QT.
An older project of mine works just quite fine in the way I've written it...
I do not understand it...

But, thanks for your help at this point.
*quiteconfused*

Björn

> -----Ursprüngliche Nachricht-----
> Von: Bauer Thomas [mailto:Thomas.Bauer@fh-joanneum.at]
> Gesendet: Dienstag, 12. März 2002 16:20
> An: 'BERG@genesys-e.de'; 'Soeren.Fietzke@t-online.de'; QT Mailing List
> (E-Mail)
> Betreff: AW: Linker error in VS 6.0 - the code
> 
> 
> OK... now it's obvious.
> Either declare 'CAboutDialog::CAboutDialog(QWidget *parent, const char
> *name, WFlags f)' inline or put the implementation directly 
> into the class
> declaration or, what's probably the most elegant solution, 
> put it inzo a
> separate .cpp file. Then it should link properly.
> 
> Tom
> 
> 
> -----Ursprüngliche Nachricht-----
> Von: "Berg, Björn" [mailto:BERG@genesys-e.de]
> Gesendet: Dienstag, 12. März 2002 16:04
> An: 'Soeren.Fietzke@t-online.de'; QT Mailing List (E-Mail)
> Betreff: AW: Linker error in VS 6.0 - the code
> 
> 
> Okay, I'm now posting the code of the two project files:
> 
> aboutdialog.h:
> 
> #include <qwidget.h>
> #include <qmultilineedit.h>
> #include <qpushbutton.h>
> #include <qlayout.h>
> 
> class CAboutDialog : public QWidget
> {
> 	Q_OBJECT
> public:
> 	CAboutDialog(QWidget *parent = 0, const char *name = 0, 
> WFlags f = 0
> );
> 
> private:
> 	QMultiLineEdit *info;
> };
> 
> CAboutDialog::CAboutDialog(QWidget *parent, const char *name, WFlags
> f):QWidget(parent,name,f)
> {
> 	//setFixedSize(200,250); //x,y of window
> 	
> 	//Widgets erzeugen
> 	info = new QMultiLineEdit (this);
> 	info->setGeometry (10,10,180,200);
> 	QPushButton *okay = new QPushButton ("OK",this,"okay");
> 
> 	//Layout erzeugen und aktivieren (anzeigen)
> 	QVBoxLayout *infoLayout = new QVBoxLayout (this,10);
> 	QHBoxLayout *buttonLayout = new QHBoxLayout ();
> 	infoLayout->addWidget(info);
>     infoLayout->addLayout(buttonLayout);
> 	buttonLayout->addWidget(okay);
> 	infoLayout->activate();
> 
> 	//Eigenschfaten festlegen
> 	connect(okay,SIGNAL(clicked()),this,SLOT(quit()));
> 	info->setReadOnly(TRUE);
> 	this->setCaption("About");
> }
> '''''''''''''''''''''''''''''''''''''''''''''''''''''
> main.cpp:
> 
> #include <qapplication.h>
> #include "aboutdialog.h"
> 
> 
> int main( int argc, char** argv )
> {
> 	QApplication app( argc, argv );
> 
> 	CAboutDialog d;
> 	//app.setMainWidget(&dialog);
> 
> 	d.show();
> 
> 	return app.exec();
> }
> 
> Hope that gives you more information...
> 
> Björn
> 
> > -----Ursprüngliche Nachricht-----
> > Von: Soeren.Fietzke@t-online.de [mailto:Soeren.Fietzke@t-online.de]
> > Gesendet: Dienstag, 12. März 2002 15:56
> > An: Berg, Björn; QT Mailing List (E-Mail)
> > Betreff: Re: Linker error in VS 6.0
> > 
> > 
> > No, no, don't do that :-)
> > On second thought, the constructor of CAboutDialog should not 
> > appear in the moc file at all.
> > If the code is not too long, perhaps just post it?
> > 
> > - Soeren
> > 
> > 
> > ----- Original Message -----
> > From: "Berg, Björn" <BERG@genesys-e.de>
> > To: <Soeren.Fietzke@t-online.de>; "QT Mailing List (E-Mail)" 
> > <qt-interest@trolltech.com>
> > Sent: Tuesday, March 12, 2002 3:50 PM
> > Subject: AW: Linker error in VS 6.0
> > 
> > 
> > No, I do not include "moc_aboutdialog.cpp" in main.cpp... Is this
> > necessary??
> > 
> > Björn
> > 
> > 
> 
> --
> List archive and information: http://qt-interest.trolltech.com
> 
> --
> List archive and information: http://qt-interest.trolltech.com
> 


Message 6 in thread

Hi,

> Only for testing I have done what you said, but the error is already there.
> For me it is very hard to understand why I should create an extra file for
> implementation or a direct implementation in the class. Normal C++ works
> with implementation outside the class best and it  is the same with QT.

No, if a compiler/linker detects multiple definitions of the same function, it is supposed to report an error. See Stroustrup,
Section 9.2.3: "The One-Definition Rule". It also lists the exception to this rule, but that exception only applies to classes,
templates and inline functions.
Because your constructor code is neither of the three, the linker barfs.
There are two ways to convert the constructor to an inline function:
1) write it completely inside the class definition
or
2) prefix both the constructor prototype in the class definition and the
   implementation with the keyword "inline"

The third way to solve this problem is to move the constructor out of the header file so that the code will not be part of every
file that includes it.

Which of the three options is the best one depends on the code in the function. Anything longer than a couple of statement is
usually best put in a separate file.

About using "/force:multiple": "For every complex problem, there is a solution that is simple, neat, and wrong" [H.L.Mencken(?)]

Have a good one,
Soeren


Message 7 in thread

Well in my case, the files that the linker barfs on are ones that are 
created by the uic/moc.  They are files created by the uic processing 
the .ui files in my project, so it isn't really code that I can do 
anything about.

For example, I have a file "pilot_display.ui" that I created in Qt 
Designer.  I have that file listed on the FORMS line in my .pro file.  I 
don't have "pilot_display.cpp" on my SOURCES line, nor do I have 
"pilot_display.h" on my HEADERS line.  So the only time where 
"pilot_display" with any extension is listed is on the 
"pilot_display.ui" entry on the FORMS line.

In Linux, this project compiles and links with no errors or warnings...

When I create the Makefile on Windows, it mentions 
"moc_pilot_display.obj" in the OBJMOC section, and "pilot_display.obj" 
in the OBJECTS section.  Visual C++ compiles everything fine, but when 
the linker starts running, it complains about EVERY function in those 
two .obj files being multiply defined.

Since it isn't really my code (it's the uic's code), I don't think I 
should have to run the uic by hand, then go in to the .cpp file it 
creates, yank out all the code from there and put all the definitions in 
the .h file that it generates.  That seems to kind of defeat the purpose!

My own classes that I have in this project follow the normal C++ 
convention of putting only the declarations in the .h file and the 
definitions in the .cpp file.  These files do not give linker errors at 
all.  It is only the files that are generated by the uic and the moc.
Sean

On Wednesday, March 13, 2002, at 06:57  AM, Soeren.Fietzke@t-online.de 
wrote:

> Hi,
>
>> Only for testing I have done what you said, but the error is already 
>> there.
>> For me it is very hard to understand why I should create an extra file 
>> for
>> implementation or a direct implementation in the class. Normal C++ 
>> works
>> with implementation outside the class best and it  is the same with QT.
>
> No, if a compiler/linker detects multiple definitions of the same 
> function, it is supposed to report an error. See Stroustrup,
> Section 9.2.3: "The One-Definition Rule". It also lists the exception 
> to this rule, but that exception only applies to classes,
> templates and inline functions.
> Because your constructor code is neither of the three, the linker barfs.
> There are two ways to convert the constructor to an inline function:
> 1) write it completely inside the class definition
> or
> 2) prefix both the constructor prototype in the class definition and the
>    implementation with the keyword "inline"
>
> The third way to solve this problem is to move the constructor out of 
> the header file so that the code will not be part of every
> file that includes it.
>
> Which of the three options is the best one depends on the code in the 
> function. Anything longer than a couple of statement is
> usually best put in a separate file.
>
> About using "/force:multiple": "For every complex problem, there is a 
> solution that is simple, neat, and wrong" [H.L.Mencken(?)]
>
> Have a good one,
> Soeren
>
> --
> List archive and information: http://qt-interest.trolltech.com


Message 8 in thread

> Tom,
> Could you explain more about why your solution needs to be done?  Does
> Visual C++ have a problem when things aren't defined in the class
> declaration or something?  If so, what types of function definitions
> need to be done in the class definition?  In my projects, I always
> declare my class functions in the .h file, then define the functions in
> the .cpp file (which I thought is the "right way" for C++), but I'd
> really like to get rid of these linker errors.

> Sean

I found out that if you put the implementation of the class's methods
directly in the header file (when not using the inline directive) MS VC++
creates a separate implementation in each compiled .obj or .lib file. This
does however not apply if you put it directly into the class declaration and
of cource not if you put it into a separate .cpp file. Another way seems to
be to specify /FORCE:mulitple in the linker options as you suggested.

Tom


Message 9 in thread

All what you say is correct except:

> 2) prefix both the constructor prototype in the class definition and the
>   implementation with the keyword "inline"

if you implement the inline function outside the class declaration only the
implementation should be prefixed with the inline keyword (although most
compilers accept the prefixed prototype, too).

Tom


-----Ursprüngliche Nachricht-----
Von: Soeren.Fietzke@t-online.de [mailto:Soeren.Fietzke@t-online.de]
Gesendet: Mittwoch, 13. März 2002 12:57
An: BERG@genesys-e.de; Thomas.Bauer@fh-joanneum.at; QT Mailing List
(E-Mail)
Betreff: Re: Linker error in VS 6.0 - the code


Hi,

> Only for testing I have done what you said, but the error is already
there.
> For me it is very hard to understand why I should create an extra file for
> implementation or a direct implementation in the class. Normal C++ works
> with implementation outside the class best and it  is the same with QT.

No, if a compiler/linker detects multiple definitions of the same function,
it is supposed to report an error. See Stroustrup,
Section 9.2.3: "The One-Definition Rule". It also lists the exception to
this rule, but that exception only applies to classes,
templates and inline functions.
Because your constructor code is neither of the three, the linker barfs.
There are two ways to convert the constructor to an inline function:
1) write it completely inside the class definition
or
2) prefix both the constructor prototype in the class definition and the
   implementation with the keyword "inline"

The third way to solve this problem is to move the constructor out of the
header file so that the code will not be part of every
file that includes it.

Which of the three options is the best one depends on the code in the
function. Anything longer than a couple of statement is
usually best put in a separate file.

About using "/force:multiple": "For every complex problem, there is a
solution that is simple, neat, and wrong" [H.L.Mencken(?)]

Have a good one,
Soeren