Klassen definitie in bronbestand

Status
Niet open voor verdere reacties.

Gvdsloot

Nieuwe gebruiker
Lid geworden
5 nov 2009
Berichten
4
Hallo, ik heb gelezen dat ik klassen moet defineren in een header bestand en de functies moet defineren in een bronbestand, ik heb 3 bestanden: date.h, date.cpp en dateTest.cpp.
Helaas krijg ik steeds de volgende error als ik datetest.cpp uitvoer:
Code:
/home/gerritjan/Bureaublad/C++ oefeningen/Tests/Klassen/Date/dateTest.o||In function `main':|
dateTest.cpp:(.text+0x7f)||undefined reference to `date::setDag(int)'|
dateTest.cpp:(.text+0x92)||undefined reference to `date::setMaand(int)'|
dateTest.cpp:(.text+0xa5)||undefined reference to `date::setJaar(int)'|
dateTest.cpp:(.text+0xb0)||undefined reference to `date::getDag()'|
dateTest.cpp:(.text+0xbd)||undefined reference to `date::getMaand()'|
dateTest.cpp:(.text+0xca)||undefined reference to `date::getJaar()'|
||=== Build finished: 6 errors, 0 warnings ===|

Ik weet niet hoe ik dit oplos, dit is de code van de bestanden:

date.h:
[CPP]class date {
private:
int dag;
int maand;
int jaar;
public:
int setDag(int dag);
int setMaand(int maand);
int setJaar(int jaar);
int getDag();
int getMaand();
int getJaar();
};
[/CPP]

Date.cpp:
[CPP]#include "date.h"

int date::getDag() {
return date::dag;
}
int date::getMaand() {
return date::maand;
}
int date::getJaar() {
return date::jaar;
}
int date::setDag(int dag) {
date::dag = dag;
}
int date::setMaand(int maand) {
date::maand = maand;
}
int date::setJaar(int jaar) {
date::jaar = jaar;
}
[/CPP]

dateTest.cpp:
[CPP]#include <iostream>
#include "date.h"

using namespace std;

int main() {
date a;

a.setDag(30);
a.setMaand(11);
a.setJaar(1994);

cout << "Jaar: " << a.getJaar() << endl << "Maand: " << a.getMaand() << endl << "Dag: " << a.getDag();

return 0;
}
[/CPP]

Ik zoek nu al een poosje en ik weet me echt geen raad meer hiermee.
 
Welke compiler gebruik je? Het lijkt er namelijk op dat date.cpp niet gecompileerd wordt. Als ik het zo probeer (Linux):
frank@darkstar:~/classtest$ g++ -Wall -ansi -c -o date.o date.cpp
date.cpp: In member function 'int date::setJaar(int)':
date.cpp:20: let op: control reaches end of non-void function
date.cpp: In member function 'int date::setMaand(int)':
date.cpp:17: let op: control reaches end of non-void function
date.cpp: In member function 'int date::setDag(int)':
date.cpp:14: let op: control reaches end of non-void function
frank@darkstar:~/classtest$ g++ -Wall -ansi -c -o dateTest.o datetest.cpp
frank@darkstar:~/classtest$ g++ -Wall -ansi -o datetest *o
frank@darkstar:~/classtest$ ./datetest
Jaar: 1994
Maand: 11
Dag: 30
dan werkt het.
 
Als ik date compileer krijg ik geen executable maar alleen een .o bestand, wat houd dat eigenlijk in?
PS: Als ik dateTest compileer krijg ik nog altijd die error.
 
Laatst bewerkt:
Als ik date compileer krijg ik geen executable maar alleen een .o bestand, wat houd dat eigenlijk in?
PS: Als ik dateTest compileer krijg ik nog altijd die error.

in datetest.cpp inlcude geen date.h maar date.cpp
 
Ik lees op andere fora dat .cpp includen een zeer slechte zaak is
 
Ik lees op andere fora dat .cpp includen een zeer slechte zaak is

1. ik snap sowieso al niet waarom je daar een appart tablad voor hebt gemaakt, maak gewoon 1.cpp

2. Waarom is .cpp includen slecht? Ik doe het wel vaker, bij grote programma's, juist handig
 
Ik zeg niet dat het slecht is maar volgens sommige fora moest je dat niet doen had ik gelezen
 
Ik zeg niet dat het slecht is maar volgens sommige fora moest je dat niet doen had ik gelezen

doe het dan gewoon zo als ik zei

Code:
#include <cstdlib>
#include <iostream>
#include <windows.h>

using namespace std;

class date {
    private:
        int dag;
        int maand;
        int jaar;
    public:
        int setDag(int dag);
        int setMaand(int maand);
        int setJaar(int jaar);
        int getDag();
        int getMaand();
        int getJaar();
};

 
int date::getDag() {
    return date::dag;
}
int date::getMaand() {
    return date::maand;
}
int date::getJaar() {
    return date::jaar;
}
int date::setDag(int dag) {
    date::dag = dag;
}
int date::setMaand(int maand) {
    date::maand = maand;
}
int date::setJaar(int jaar) {
    date::jaar = jaar;
}

int main() {
    date a;
 
    a.setDag(30);
    a.setMaand(11);
    a.setJaar(1994);
 
    cout << "Jaar: " << a.getJaar() << endl << "Maand: " << a.getMaand() << endl << "Dag: " << a.getDag();
    Sleep (10000); // om te laten zien wat er staat
    return 0;
}

werkt zonder probleem
 
ik heb gelezen dat ik klassen moet defineren in een header bestand en de functies moet defineren in een bronbestand.
Het is geen verplichting om je code te scheiden in een header- en bronbestand, maar in de C++ standaard wordt het wel sterk aangeraden om die (algemeen geaccepteerde) werkwijze aan te houden. Het scheiden van je klasse declaratie en definitie in een header en bron-bestand maakt namelijk "Separate Compilation" mogelijk. "Separate Compilation" houd in dat als je een project hebt met 100 bron bestanden en voert wijzigingen uit in 1 van deze bestanden, dan hoef je alleen dit ene bestand maar te her-compileren om een nieuwe executable te genereren. Dit levert dus snelheidswinst op tijdens het compileren, vooral bij grotere projecten.

Om goed gebruik te maken van "Separate Compilation" is het zaak dat je geen afhankelijkheden creeert tussen je bronbestanden onderling. Dit gebeurd wel wanneer je een .cpp bestand include in een ander .cpp bestand. Indien je dan in het ene .cpp bestand iets wijzigt, moeten beide opnieuw worden gecompileerd. Daarnaast kun je tegen problemen aanlopen doordat je (onbewust) globale variabelen of "using namespace xxx" mee krijgt uit het andere .cpp bestand. Daarom wordt het includen van een .cpp bestand vaak als "slecht" beschouwd.

Als ik date compileer krijg ik geen executable maar alleen een .o bestand, wat houd dat eigenlijk in?
Vanwege mijn bovenstaande verhaal bestaat het bouwen van een volledige executable uit 2 stappen;
(1) Het compileren van de .cpp bestanden tot tijdelijke object-bestanden (.o bestanden). Voor elk .cpp bestand levert dit een .o bestand op.
(2) Het samen "linken" van al deze .o bestanden tot 1 executable. Na deze stap heb je pas een echte executable.

Supersnail voert deze stappen 1 voor 1 uit in zijn uitleg;

(1) Compileren van date.cpp naar een object bestand (date.o):
Code:
$ g++ -Wall -ansi -c -o date.o date.cpp
(1) Compileren van datetest.cpp naar een object bestand (dateTest.o):
Code:
$ g++ -Wall -ansi -c -o dateTest.o datetest.cpp
(2) Samen "linken" van de zojuist gegenereerde object bestanden (*.o) tot een echte executable:
Code:
$ g++ -Wall -ansi -o datetest *o
Uitvoeren van de executable:
Code:
$ ./datetest

Het ziet er naar uit dat je probeert de .o bestanden uit te voeren. Dus het "linken" heb je waarschijnlijk nog niet gedaan, waardoor je nog geen executable hebt. Als je dit doet (net als het voorbeeld van Supersnail) zou het moeten werken.

Overigens kan dit automatisch gedaan worden, maar dat hangt af van de manier waarop je compileert.
 
Laatst bewerkt:
[cpp]
class date {
private:
int dag;
int maand;
int jaar;
public:
int setDag(int dag);
int setMaand(int maand);
int setJaar(int jaar);
int getDag();
int getMaand();
int getJaar();
};
[/cpp]

De functies setDag, setMaand en setJaar hebben overigens allemaal het verkeerde return type. Omdat je de functies alleen maar nodig hebt voor hun acties, en ze ook niks returnen maak je er beter het type void van.

[cpp]
class date {
private:
int dag;
int maand;
int jaar;
public:
/*
Verder zou je ook nog een constructor kunnen toevoegen zodat je een date object kunt aanmaken in de vorm van 'date d(7,11,2009)'
->
date(const int dag, const int maand, const int jaar); // eventueel standaard waardes geven
*/
void setDag(const int dag);
void setMaand(const int maand);
void setJaar(const int jaar);
int getDag() const;
int getMaand() const;
int getJaar() const;
};[/cpp]
 
Laatst bewerkt:
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan