"undefined reference to" error, pointer vraag en #if, #ifndef en #endif vraag

Status
Niet open voor verdere reacties.

Voldemort

Gebruiker
Lid geworden
21 jul 2006
Berichten
111
Hoi iedereen,

Ik ben aan het proberen een eigen MSN client te schrijven. Ik ben eraan begonnen, maar nu krijg ik dit als error:

Code:
window_login.o: In function `Window_Login::StartLogin()':
window_login.cpp:(.text+0x1e): undefined reference to `msn'
window_login.cpp:(.text+0x51): undefined reference to `msn'
window_login.cpp:(.text+0x7d): undefined reference to `msn'

Code:

main.cpp
Code:
#include <iostream>
#include <QApplication>

#include "window_login.h"
#include "cmsn/cmsn.h"

using namespace std;

int main(int argc, char *argv[])
{
	cmsn *msn = NULL;
	msn = new cmsn();

	QApplication app(argc, argv);
	Window_Login Window_Login;
	Window_Login.show();
	return app.exec();
}

window_login.cpp
Code:
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>

#include "window_login.h"
#include "cmsn/cmsn.h"

extern cmsn *msn;

Window_Login::Window_Login()
{
	QLabel *lblUserName = new QLabel(tr("Mailadres:"));
	QLabel *lblPass = new QLabel(tr("Wachtwoord:"));
	QLabel *lblLogin = new QLabel(tr("Aanmelden:"));

	mail = new QLineEdit;

	pass = new QLineEdit;
	pass->setEchoMode(QLineEdit::Password);

	QPushButton *login = new QPushButton(tr("Aanmelden"));

	QGridLayout *lay_ok = new QGridLayout;
	lay_ok->addWidget(lblUserName,0,0);
	lay_ok->addWidget(mail,1,0);
	lay_ok->addWidget(lblPass,2,0);
	lay_ok->addWidget(pass,3,0);
	lay_ok->addWidget(lblLogin,4,0);
	lay_ok->addWidget(login,5,0);
	setLayout(lay_ok);

	connect(login, SIGNAL(clicked()), this, SLOT(StartLogin()));
}

void Window_Login::StartLogin()
{
	msn->setMail(mail->text());
	msn->setPass(pass->text());

	msn->StartLogin();
}

window_login.h
Code:
#include <QWidget>
#include <QLineEdit>

class Window_Login : public QWidget
{
	Q_OBJECT

	public:
		Window_Login();

	private slots:
		void StartLogin();

	private:
		QLineEdit *mail;
		QLineEdit *pass;
};

cmsn/cmsn.cpp
Code:
#include <QString>

#include "cmsn.h"

cmsn::cmsn()
{
	
}

void cmsn::setMail(QString mailaddr)
{
	mail = mailaddr;
}

void cmsn::setPass(QString passww)
{
	pass = passww;
}

void cmsn::StartLogin()
{
	
}

void cmsn::SendData()
{
	
}

void cmsn::HandleData()
{
	
}

cmsn.h
Code:
#include <QString>

class cmsn
{
	public:
		cmsn();
		void setMail(QString mailaddr);
		void setPass(QString passww);
		void StartLogin();
		void SendData();
		void HandleData();

		QString mail;
		QString pass;
};

De reden dat er functies zijn waarin niks gebeurt is omdat ik ze nog moet maken.

Ik maak gebruik van Qt 4.2, maar ik denk niet dat het probleem bij Qt ligt, eerder bij die extern. Nu zijn mij vragen:

1) Waarom krijg ik deze errors en hoe los ik ze op?
2) in mijn main.cpp weet ik dat ik normaal delete msn moet doen, maar wanneer? Die variable heb ik overal nodig, dus wanneer moet ik delete msn doen?
3) Waarvoor dienen #if, #ifndef en #endif? Is dit de oplossing tot mijn probleem?
 
Laatst bewerkt:
Ik denk dat het linker errors zijn, dit komt denk zoals ik het zo zie je alleen msn als ertern declareerd maar deze nergens implementeerd:
PHP:
extern cmsn *msn;

Je zal ergens in een cpp bestand deze moeten implementeren:
HTML:
cmsn* msn = new cmsn(); //ofzo
 
over #if #ifndef #ifdef #endif

regels die met een hekje (#) beginnen noemt men pre-compiler-derectives.
Het zijn opdrachten die tijdens de compilatie uitgevoerd worden.

De meest gekende is natuurlijk '#include' die ervoor zorgt dat de inhoud van het geïnclude bestand op die plaats wordt ingevoegd.

Een andere veelgebruikte is '#define' die wordt gebruikt om een term/waarde te definiëren. Als je define gebruikt om een waarde te definiëren kan je de term van de definitie in je code gebruiken, bij compilatie wordt deze dan vervangen.

Code:
#define MAX_CONN 5; //maximaal aantal connecties
//en dan verder in het programma
int i = 2;
if (i < MAX_CONN) ...


Het meest gebruikte voorkomen (bij mijn weten dan toch) van deze pre-compiler-directives is bij het gebruik van header-files.
In een programma mag/moet elke functie eenduidig gedefinieerd zijn. Daarom is het volgende bvb fout:
Code:
void show() { cout << "show1"; }
void show() { cout << "show2"; }
Wanneer je nu show() oproept kan de compiler onmogelijk weten welke functie je nu wil gebruiken.
Als je eenzelfde header in verschillende .cpp's nodig hebt (bvb iostream) en elke include zou uitgevoerd worden (zijn lijn vervangen door de code van iostream) zie je zelf dat je meerdere malen exact dezelfde code zal hebben. Daarom is in iostream volgend if-statement opgenomen:
Code:
#ifndef _GLIBCXX_IOSTREAM
        #define _GLIBCXX_IOSTREAM 1
        //alle code van iostream
#endif
De eerste maal dat iostream geïnclude wordt, kijkt de compiler of de term _GLIBCXX_IOSTREAM al bestaat met #ifndef (if not defined -> als niet gedefiniëerd)
Als de term nog niet bestaat wordt alle code binnen het ifstatement uitgevoerd. Met als eerste de definitie van de term _GLIBCXX_IOSTREAM zodat bij een volgende include de if false wordt en alle functiedefinities niet meer gekopiëerd worden naar jouw code.
Het einde van de if wordt aangegeven door #endif

--Johan
 
Ik denk dat het linker errors zijn, dit komt denk zoals ik het zo zie je alleen msn als ertern declareerd maar deze nergens implementeerd:
PHP:
extern cmsn *msn;

Je zal ergens in een cpp bestand deze moeten implementeren:
HTML:
cmsn* msn = new cmsn(); //ofzo

Deze staat in mijn main.cpp.
 
Ik heb die extern eruit gewipt en ik heb nu dit:

main.cpp
Code:
#include <iostream>
#include <QApplication>

#include "window_login.h"

using namespace std;

//Main functie
int main(int argc, char *argv[])
{
	cmsn *msn = NULL;
	msn = new cmsn();

	QApplication app(argc, argv);
	Window_Login *login = new Window_Login(msn);
	login->show();

	return app.exec();
}

window_login.cpp
Code:
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QDialog>
#include <QString>

#include "window_login.h"

Window_Login::Window_Login(cmsn *msn)
{
	QLabel *lblUserName = new QLabel(tr("Mailadres:"));
	QLabel *lblPass = new QLabel(tr("Wachtwoord:"));
	QLabel *lblLogin = new QLabel(tr("Aanmelden:"));

	mail = new QLineEdit;

	pass = new QLineEdit;
	pass->setEchoMode(QLineEdit::Password);

	QPushButton *blogin = new QPushButton(tr("Aanmelden"));

	QGridLayout *lay_ok = new QGridLayout;
	lay_ok->addWidget(lblUserName,0,0);
	lay_ok->addWidget(mail,1,0);
	lay_ok->addWidget(lblPass,2,0);
	lay_ok->addWidget(pass,3,0);
	lay_ok->addWidget(lblLogin,4,0);
	lay_ok->addWidget(blogin,5,0);
	setLayout(lay_ok);

	connect(blogin, SIGNAL(clicked()), this, SLOT(startLogin(cmsn*)));
}

void Window_Login::startLogin(cmsn* msn)
{
	msn->setMail(mail->text());
	msn->setPass(pass->text());

	msn->StartLogin();

	//De volgende 7 regels zijn enkel om te testen, dit verwijder ik als ik weet dat het werkt
	mail->clear();
	mail->insert(tr("Test "));
	mail->insert(msn->mail);

	pass->clear();
	pass->insert(tr("Test2 "));
	pass->insert(msn->pass);
}

window_login.h
Code:
#include <QWidget>
#include <QLineEdit>

#include "cmsn/cmsn.h"

class Window_Login : public QWidget
{
	Q_OBJECT

	public:
		Window_Login(cmsn *msn);

	private slots:
		void startLogin(cmsn *msn);

	private:
		QLineEdit *mail;
		QLineEdit *pass;
};

cmsn.cpp
Code:
#include <QString>

#include "cmsn.h"

cmsn::cmsn()
{
	
}

void cmsn::setMail(QString mailaddr)
{
	mail = mailaddr;
}

void cmsn::setPass(QString passww)
{
	pass = passww;
}

void cmsn::StartLogin()
{
	
}

void cmsn::SendData()
{
	
}

void cmsn::HandleData()
{
	
}

cmsn.h
Code:
#include <QString>

class cmsn
{
	public:
		cmsn();
		void setMail(QString mailaddr);
		void setPass(QString passww);
		void StartLogin();
		void SendData();
		void HandleData();

		QString mail;
		QString pass;
};

1) Compilen doe ie goed, maar als ik het programma uitvoer krijg ik dit van Qt:

QObject::connect: Incompatible sender/receiver arguments
QPushButton::clicked() --> Window_Login::startLogin(cmsn*)

En er gebeurt ook niks als ik op die button klik.

2) in mijn main.cpp weet ik dat ik normaal delete msn en delete login moet doen (ivm memory leaks), maar wanneer? Die variable heb ik overal nodig, dus wanneer moet ik delete msn doen? Als ik het net voor de return doe opent mijn programma, maar sluit het meteen weer. Waar moet het dan?
 
1)
Code:
connect(blogin, SIGNAL(clicked()), this, SLOT(startLogin(cmsn*)));
dit komt niet met elkaar overeen. Een Slot moet dezelfde parameters (of minder) als een Signal bevatten. Dus je kunt cmsn* niet op deze manier aan je slot toevoegen als deze niet door het Signal uitgezonden wordt.

2)
het deleten zou je toch na het aanroepen van de "exec" kunnen doen?
 
1)
Code:
connect(blogin, SIGNAL(clicked()), this, SLOT(startLogin(cmsn*)));
dit komt niet met elkaar overeen. Een Slot moet dezelfde parameters (of minder) als een Signal bevatten. Dus je kunt cmsn* niet op deze manier aan je slot toevoegen als deze niet door het Signal uitgezonden wordt.

Hoe kan ik dit dan oplossen? clicked is een functie gemaakt door Qt zelf, hoe kan ik daar dan die cmsn* bijvoegen?

2)
het deleten zou je toch na het aanroepen van de "exec" kunnen doen?

Na return stopt de code, dus de delete zou toch nooit uitgevoerd worden. Of bedoel je het anders?
 
1) De functies van Qt kun je niet zomaar aanpassen. Dus daarvoor zou je moeten zorgen dat de pionter die je meegeeft aan je class via "Window_Login(cmsn *msn)" ook in je methode beschikbaar is zonder dat je deze als parameter meegeeft. Bijvoorbeeld door in je header een pointer te definieren, die je gebruikt om in je class naar de pointer msn te refereren.

2) Na de return stop de code inderdaad, maar wat je wel zou kunnen doen is het resultaat van de exec (tijdelijk) opvangen in een variabele (exec geeft gewoonlijk een int terug). Dan kun je daarna alsnog code uitvoeren en na die code het resultaat van de exec "returnen".
 
1) De functies van Qt kun je niet zomaar aanpassen. Dus daarvoor zou je moeten zorgen dat de pionter die je meegeeft aan je class via "Window_Login(cmsn *msn)" ook in je methode beschikbaar is zonder dat je deze als parameter meegeeft. Bijvoorbeeld door in je header een pointer te definieren, die je gebruikt om in je class naar de pointer msn te refereren.

Dit lukt niet echt:

window_login.cpp
Code:
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QDialog>
#include <QString>

#include "window_login.h"

Window_Login::Window_Login()
{
	QLabel *lblUserName = new QLabel(tr("Mailadres:"));
	QLabel *lblPass = new QLabel(tr("Wachtwoord:"));
	QLabel *lblLogin = new QLabel(tr("Aanmelden:"));

	mail = new QLineEdit;

	pass = new QLineEdit;
	pass->setEchoMode(QLineEdit::Password);

	QPushButton *blogin = new QPushButton(tr("Aanmelden"));

	QGridLayout *lay_ok = new QGridLayout;
	lay_ok->addWidget(lblUserName,0,0);
	lay_ok->addWidget(mail,1,0);
	lay_ok->addWidget(lblPass,2,0);
	lay_ok->addWidget(pass,3,0);
	lay_ok->addWidget(lblLogin,4,0);
	lay_ok->addWidget(blogin,5,0);
	setLayout(lay_ok);

	connect(blogin, SIGNAL(clicked()), this, SLOT(startLogin()));
}

void Window_Login::startLogin()
{
	*msn_point->setMail(mail->text());
	*msn_point->setPass(pass->text());

	*msn_point->StartLogin();

	mail->clear();
	mail->insert(tr("Test "));
	mail->insert(*msn_point->mail);

	pass->clear();
	pass->insert(tr("Test2 "));
	pass->insert(*msn_point->pass);
}

window_login.h
Code:
#include <QWidget>
#include <QLineEdit>

#include "cmsn/cmsn.h"

cmsn *msn_point = &msn;

class Window_Login : public QWidget
{
	Q_OBJECT

	public:
		Window_Login();

	private slots:
		void startLogin();

	private:
		QLineEdit *mail;
		QLineEdit *pass;
};

main.cpp
Zie onder.

Nu krijg ik de error:
src/window_login.h:26: error: ‘msn’ was not declared in this scope

Hoe los ik dit op?





2) Na de return stop de code inderdaad, maar wat je wel zou kunnen doen is het resultaat van de exec (tijdelijk) opvangen in een variabele (exec geeft gewoonlijk een int terug). Dan kun je daarna alsnog code uitvoeren en na die code het resultaat van de exec "returnen".

Dit werkt:

main.cpp
Code:
#include <iostream>
#include <QApplication>

#include "window_login.h"

using namespace std;

//Main functie
int main(int argc, char *argv[])
{
	int exec;

	cmsn *msn = NULL;
	msn = new cmsn();

	QApplication app(argc, argv);
	Window_Login *login = new Window_Login();
	login->show();

	exec = app.exec();

	delete msn;
	delete login;

	return exec;
}

Is dit een goede manier?
 
Laatst bewerkt:
Ik had meer iets als dit in gedachten:

window_login.h
Code:
class Window_Login : public QWidget
{
	Q_OBJECT

	public:
		Window_Login(cmsn* msn);

	private:
		cmsn *msn_point 
};

window_login.cpp
Code:
void Window_Login::startLogin(cmsn* msn)
{
	msn_point = msn;
}

main
Code:
int main(int argc, char *argv[])
{
	cmsn *msn = new cmsn();

	Window_Login *login = new Window_Login(msn);

}
Plus alle code die ik voor het gemak weg heb gelaten natuurlijk ;)
Ik heb het overigens niet getest op deze manier :)

En zoals als je de main nu hebt aangepast is het een goede methode. Je zou zelfs het try, catch, throw principe kunnen gebruiken wil je het helemaal netjes doen.
 
Ik heb nu deze code:

window_login.cpp
Code:
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QDialog>
#include <QString>

#include "window_login.h"

Window_Login::Window_Login(cmsn* msn)
{
	msn_point = msn;

	QLabel *lblUserName = new QLabel(tr("Mailadres:"));
	QLabel *lblPass = new QLabel(tr("Wachtwoord:"));
	QLabel *lblLogin = new QLabel(tr("Aanmelden:"));

	mail = new QLineEdit;

	pass = new QLineEdit;
	pass->setEchoMode(QLineEdit::Password);

	QPushButton *blogin = new QPushButton(tr("Aanmelden"));

	QGridLayout *lay_ok = new QGridLayout;
	lay_ok->addWidget(lblUserName,0,0);
	lay_ok->addWidget(mail,1,0);
	lay_ok->addWidget(lblPass,2,0);
	lay_ok->addWidget(pass,3,0);
	lay_ok->addWidget(lblLogin,4,0);
	lay_ok->addWidget(blogin,5,0);
	setLayout(lay_ok);

	connect(blogin, SIGNAL(clicked()), this, SLOT(startLogin()));
}

void Window_Login::startLogin()
{
	msn_point->setMail(mail->text());
	msn_point->setPass(pass->text());

	msn_point->StartLogin();

	mail->clear();
	mail->insert(tr("Test "));
	mail->insert(msn_point->mail);

	pass->clear();
	pass->insert(tr("Test2 "));
	pass->insert(msn_point->pass);
}

window_login.h
Code:
#include <QWidget>
#include <QLineEdit>

#include "cmsn/cmsn.h"

class Window_Login : public QWidget
{
	Q_OBJECT

	public:
		Window_Login(cmsn* msn);

	private slots:
		void startLogin();

	private:
		QLineEdit *mail;
		QLineEdit *pass;
		cmsn *msn_point;
};

main.cpp
Code:
#include <iostream>
#include <QApplication>

#include "window_login.h"

using namespace std;

//Main functie
int main(int argc, char *argv[])
{
	int exec;

	cmsn *msn = new cmsn();

	QApplication app(argc, argv);
	Window_Login *login = new Window_Login(msn);
	login->show();

	exec = app.exec();

	delete msn;
	delete login;

	return exec;
}

En deze doet het goed.

Nu nog 1 vraag:
1) Moet ik nu ook in mijn "StartLogin" functie dit doen (aan het einde van de functie):

Code:
delete msn_point;

?

Edit:

Ik denk dat ik toch liever met die extern werkt, maar ik krijg telkens dit:

Code:
window_login.cpp:(.text+0x1e): undefined reference to `msn'
window_login.cpp:(.text+0x51): undefined reference to `msn'
window_login.cpp:(.text+0x98): undefined reference to `msn'

Dit is de code (let niet op de delen die als commentaar staan):

window_login.cpp
Code:
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QString>

#include "cmsn/cmsn.h"
#include "window_login.h"
#include "window_login_busy.h"

extern cmsn *msn;

Window_Login::Window_Login(/*cmsn* msn*/)
{
	//msn_point = msn;

	QLabel *lblUserName = new QLabel(tr("Mailadres:"));
	QLabel *lblPass = new QLabel(tr("Wachtwoord:"));
	QLabel *lblLogin = new QLabel(tr("Aanmelden:"));

	mail = new QLineEdit;

	pass = new QLineEdit;
	pass->setEchoMode(QLineEdit::Password);

	QPushButton *blogin = new QPushButton(tr("Aanmelden"));

	QGridLayout *lay_ok = new QGridLayout;
	lay_ok->addWidget(lblUserName,0,0);
	lay_ok->addWidget(mail,1,0);
	lay_ok->addWidget(lblPass,2,0);
	lay_ok->addWidget(pass,3,0);
	lay_ok->addWidget(lblLogin,4,0);
	lay_ok->addWidget(blogin,5,0);
	setLayout(lay_ok);

	connect(blogin, SIGNAL(clicked()), this, SLOT(close()));
	connect(blogin, SIGNAL(clicked()), this, SLOT(startLogin()));
}

void Window_Login::startLogin()
{
	//Variablen goed zetten
	msn/*_point*/->setMail(mail->text());
	msn/*_point*/->setPass(pass->text());

	//Toon het nieuwe venster (login_busy)
	Window_Login_Busy *login_busy = new Window_Login_Busy();
	login_busy->show();

	//De functie aanroepen die de socket opent en het eerst commando zend
	msn/*_point*/->StartLogin();
}

window_login.h
Code:
#include <QWidget>
#include <QLineEdit>

class Window_Login : public QWidget
{
	Q_OBJECT

	public:
		Window_Login(/*cmsn* msn*/);

	private slots:
		void startLogin();

	private:
		QLineEdit *mail;
		QLineEdit *pass;
		//cmsn *msn_point;
};

main.cpp
Code:
#include <iostream>
#include <QApplication>

#include "cmsn/cmsn.h"
#include "window_login.h"

using namespace std;

//Main functie
int main(int argc, char *argv[])
{
	int exec;

	cmsn *msn = new cmsn();

	QApplication app(argc, argv);
	Window_Login *login = new Window_Login(/*msn*/);
	login->show();

	exec = app.exec();

	delete msn;
	delete login;

	return exec;
}

cmsn.cpp
Code:
#include <QString>
#include <QByteArray>

#include "cmsn.h"

cmsn::cmsn()
{
	step = 0;

	socket = new QTcpSocket();

	//connect(socket, SIGNAL(readyRead()), this, SLOT(handleData()));
}

void cmsn::setMail(QString mailaddr)
{
	mail = mailaddr;
}

void cmsn::setPass(QString passww)
{
	pass = passww;
}

void cmsn::StartLogin()
{
	//Open socket
	socket->connectToHost("messenger.hotmail.com",1863);
	sendData(makeData("VER"));
}

void cmsn::sendData(QString message)
{
	QByteArray data = message.toLatin1();
	socket->write(data);
}

void cmsn::handleData()
{
	
}

QString cmsn::makeData(QString command)
{
	QString message;
	step++;

	if(command == "VER")
	{
		message = "VER " + QString::number(step) + "MSNP9 CVR0";
	}

	return message;
}

cmsn.h
Code:
#include <QString>
#include <QTcpSocket>

class cmsn
{
	public:
		cmsn();
		void setMail(QString mailaddr);
		void setPass(QString passww);
		void StartLogin();
		void sendData(QString message);
		QString makeData(QString command);

		QString mail;
		QString pass;
		QTcpSocket *socket;

	public slots:
		void handleData();

	private:
		int step;
};

2) Wat gaat er mis?
 
Laatst bewerkt:
1) Moet ik nu ook in mijn "StartLogin" functie dit doen (aan het einde van de functie):

Code:
delete msn_point;
Als het goed is dan is msn_point een pointer naar msn en heb je dus maar 1 object. Die kun je dan ook maar 1 keer verwijderen.

2) Wat gaat er mis?
Aan de foutmelding te zien kan 'msn' niet gevonden worden. Dat zou kunnen komen doordat die binnen de main() functie wordt gedeclareerd.
 
Ik heb het buiten de main gedeclareerd en nu doet ie het zonder errors.

1) Alleen snap ik nog steeds niet echt goed waarvoor die #ifndef, etc echt nuttig zijn. Ik zie vaak (in open-source projecten) dit:

headerfile.h
Code:
#ifndef HEADERFILE_H
#define HEADERFILE_H

class [...]

#endif

Waarvoor is dit dan precies nodig?

2) Ik krijg deze error:

src/cmsn/cmsn.cpp:32: error: ‘connect’ was not declared in this scope

cmsn.cpp
Code:
#include <QString>
#include <QByteArray>

#include "cmsn.h"

cmsn::cmsn()
{
	step = 0;

	socket = new QTcpSocket();

	connect(socket, SIGNAL(readyRead()), this, SLOT(handleData()));
}

void cmsn::setMail(QString mailaddr)
{
	mail = mailaddr;
}

void cmsn::setPass(QString passww)
{
	pass = passww;
}

void cmsn::StartLogin()
{
	//Open socket
	socket->connectToHost("messenger.hotmail.com",1863);
	sendData(makeData("VER"));
}

void cmsn::sendData(QString message)
{
	QByteArray data = message.toLatin1();
	socket->write(data);
}

void cmsn::handleData()
{
	
}

QString cmsn::makeData(QString command)
{
	QString message;
	step++;

	if(command == "VER")
	{
		message = "VER " + QString::number(step) + "MSNP9 CVR0";
	}

	return message;
}

cmsn.h
Code:
#include <QString>
#include <QTcpSocket>

class cmsn
{
	public:
		cmsn();
		void setMail(QString mailaddr);
		void setPass(QString passww);
		void StartLogin();
		void sendData(QString message);
		QString makeData(QString command);

		QString mail;
		QString pass;
		QTcpSocket *socket;

	public slots:
		void handleData();

	private:
		int step;
};

Ik heb bij cmsn.cpp al geprobeerd dit bovenin te zetten

#include <QObject>

of dit:

#include <QWidget>

Maar dat hielp niks. Waarom herkent ie plots de connect functie niet meer?
 
Laatst bewerkt:
1) Dit dient ervoor om de code maar 1 te compileren en rare effecten te voorkomen wanneer een bestand meerdere keren wordt geinclude.

2) Dat kan komen omdat je in elke klasse de term "Q_OBJECT" op moet nemen wil je het signal en slot mechanisme kunnen gebruiken. Qt voegt dan bij het compilen extra code toe om het mechanisme te laten werken.
 
Laatst bewerkt:
1) Waarom include je dat header bestand dan 2 keer, de 2e keer gebeurt er toch niks.

2) Ik heb Q_OBJECT toegevoegd (stomme fout) en nu krijg ik deze errors:

Code:
src/cmsn/cmsn.h:25: warning: ‘class cmsn’ has virtual functions but non-virtual destructor

[Dit zo'n 3x met elke keer een commando ertussen en daaronder dan dit:]

src/cmsn/cmsn.cpp: In constructor ‘cmsn::cmsn()’:
src/cmsn/cmsn.cpp:32: error: ‘connect’ was not declared in this scope

Wat doe ik nu fout? Ik gebruik toch nergens virtual (ik zou zelfs niet weten waar het goed voor is)? En die connect, waarom wil ie die niet herkennen?

cmsn.cpp
Code:
#include <QString>
#include <QByteArray>

#include "cmsn.h"

cmsn::cmsn()
{
	step = 0;

	socket = new QTcpSocket();

	connect(socket, SIGNAL(readyRead()), this, SLOT(getData()));
}

void cmsn::setMail(QString mailaddr)
{
	mail = mailaddr;
}

void cmsn::setPass(QString passww)
{
	pass = passww;
}

void cmsn::StartLogin()
{
	//Open socket
	socket->connectToHost("messenger.hotmail.com",1863);
	sendData(makeData("VER"));
}

void cmsn::sendData(QString message)
{
	QByteArray data = message.toLatin1();
	socket->write(data);
}

void cmsn::getData()
{
	//Read
	if(socket->canReadLine())
		handleData(socket->readLine());
}

QString cmsn::makeData(QString command)
{
	QString message;
	step++;

	if(command == "VER")
	{
		message = "VER " + QString::number(step) + " MSNP9 CVR0";
	}
	else if(command == "CVR")
	{
		message = "CVR " + QString::number(step) + " 0x0409 winnt 5.1 i386 MSNMSGR 6.0.0602 MSMSGS " + mail;
	}

	return message;
}

void cmsn::handleData(QString data)
{
	//VER terug gekregen ==> CVR verzenden
	if(data.section(" ",0,0) == "VER")
	{
		//CVR maken
		QByteArray toSend = makeData("CVR").toLatin1();

		//CVR verzenden
		socket->write(toSend);
	}
	//CVR terug gekregen ==> USR verzenden
	else if(data.section(" ",0,0) == "CVR")
	{
		
	}
}

cmsn.h
Code:
#include <QString>
#include <QTcpSocket>

class cmsn
{
	Q_OBJECT

	public:
		cmsn();
		void setMail(QString mailaddr);
		void setPass(QString passww);
		void StartLogin();
		void sendData(QString message);
		QString makeData(QString command);
		void handleData(QString data);

		QString mail;
		QString pass;
		QTcpSocket *socket;

	public slots:
		void getData();

	private:
		int step;
};
 
1) Het komt vaak voor dat je op verschillende plekken dezelfde classes wil gebruiken, zie het bericht van johan: http://www.helpmij.nl/forum/showthread.php?p=1869523#3

Maar de 2e keer dat je het bestand include gebeurt er niks, waarom include met het bestand dan een 2e keer?

2) Om een connect uit te voeren zul je je klasse ook nog van QObject af moeten leiden, anders zal deze ook niet werken.

Ik snap dit niet echt. Moet ik de klasse QObject over laten erven in mijn klasse cmsn? Of bedoel je het anders?
 
Maar de 2e keer dat je het bestand include gebeurt er niks, waarom include met het bestand dan een 2e keer?

Anders kun je problemen krijgen als je bijvoorbeeld iets als dit doet:

bestand b.cpp
Code:
#include a.cpp

bestand c.cpp
Code:
#include a.cpp
#include b.cpp

zeker als je niet precies weet hoe je de onderliggende libraries in elkaar zitten kan dat zeer handig zijn. Anders zou je zelfs een loop kunnen creeeren.


Ik snap dit niet echt. Moet ik de klasse QObject over laten erven in mijn klasse cmsn? Of bedoel je het anders?
Inderdaad. Je moet QObject overerven of een klasse die al van QObject is overgeërfd.
 
Nu krijg ik weer een linker error:

Code:
cmsn.o: In function `cmsn::cmsn()':
cmsn.cpp:(.text+0x177): undefined reference to `vtable for cmsn'
cmsn.o: In function `cmsn::cmsn()':
cmsn.cpp:(.text+0x287): undefined reference to `vtable for cmsn'

cmsn.cpp
Code:
#include <iostream>

#include <QString>
#include <QByteArray>

#include "cmsn.h"

using namespace std;

cmsn::cmsn()
{
	step = 0;

	socket = new QTcpSocket();

	connect(socket, SIGNAL(readyRead()), this, SLOT(getData()));
}

void cmsn::setMail(QString mailaddr)
{
	mail = mailaddr;
}

void cmsn::setPass(QString passww)
{
	pass = passww;
}

void cmsn::StartLogin()
{
	cout << "Socket connected.";

	//Open socket
	socket->connectToHost("messenger.hotmail.com",1863);
	sendData(makeData("VER"));
}

void cmsn::sendData(QString message)
{
	cout << "Message sended.";

	QByteArray data = message.toLatin1();
	socket->write(data);
}

void cmsn::getData()
{
	cout << "Received message from server.";

	//Read
	if(socket->canReadLine())
		handleData(socket->readLine());
}

QString cmsn::makeData(QString command)
{
	QString message;
	step++;

	if(command == "VER")
	{
		cout << "VER made";
		message = "VER " + QString::number(step) + " MSNP9 CVR0";
	}
	else if(command == "CVR")
	{
		cout << "CVR made";
		message = "CVR " + QString::number(step) + " 0x0409 winnt 5.1 i386 MSNMSGR 6.0.0602 MSMSGS " + mail;
	}

	return message;
}

void cmsn::handleData(QString data)
{
	//VER terug gekregen ==> CVR verzenden
	if(data.section(" ",0,0) == "VER")
	{
		cout << "CVR sended";

		//CVR maken
		QByteArray toSend = makeData("CVR").toLatin1();

		//CVR verzenden
		socket->write(toSend);
	}
	//CVR terug gekregen ==> USR verzenden
	else if(data.section(" ",0,0) == "CVR")
	{
		
	}
}

cmsn.h
Code:
#include <QString>
#include <QTcpSocket>
#include <QObject>

class cmsn : public QObject
{
	Q_OBJECT

	public:
		cmsn();
		void setMail(QString mailaddr);
		void setPass(QString passww);
		void StartLogin();
		void sendData(QString message);
		QString makeData(QString command);
		void handleData(QString data);

		QString mail;
		QString pass;
		QTcpSocket *socket;

	public slots:
		void getData();

	private:
		int step;
};

Zelfs als ik alles in de constructor als commentaar zet geeft ie nog steeds die linker error.
1) Wat is er nu fout?
2) Wat is een vtable eigenlijk?

3) Die #define, in jouw voorbeeld kan je dan toch in b.cpp die #include "a.cpp" weglaten? Ik snap nog steeds niet echt waarom het zo nuttig is, want de 2e keer gebeurt er niks.
4) Waarom include men dan toch nog die header, als er gebeurd dan toch niks met die header? Dus waarom zou men die dan include'en?
 
1) ik weet niet of de melding hier door komt, maar in cmsn.h heb je de overerverving toegevoegd, maar in cmsn.cpp nog niet.

2) Zou ik zo niet kunnen zeggen.

3) 4) In mijn voorbeeld zou je ene inderdaad weg kunnen laten, maar het wordt lastiger als je gebruik maakt van libraries die geen #define e.d. gebruiken.

Een Qt voorbeeld: stel dat je een in een programma een QDateEdit en een QTimeEdit wil gebruiken. Hiervoor voeg je netjes "#include <QDateEdit>" en "#include <QTimeEdit>" toe. Dit vormt echter al een probleem aangezien beide klassen zijn afgeleid van QObject. Je include dus netjes de beide klassen, maar ondertussen ook 2x QObject. Doordat Qt #define e.d. gebruikt wordt voorkomen dat je "Class redefinition errors" krijgt.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan