[C++] "multiple definition of" error

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben op dit moment bezig met dictaat van Jeroen Fokker en neem dus letterlijk zijn code over, alleen werkt het bij mij niet.

Binnen één project zijn er 7 files:
List.hpp
Queue.hpp
Net.hpp --> NetBuild.cpp
--> NetPrint.cpp
--> NetZoek.cpp
--> NetMain.cpp

NetBuild.cpp included Net.hpp en implementeert alle methoden die met builden te maken hebben.
NetPrint.cpp included Net.hpp en implementeert alle methoden die met printen te maken hebben.
NetZoek.cpp included Net.hpp en implementeert alle methoden die met zoeken te maken hebben.

List.hpp en Queue.hpp worden in de Net.hpp geincluded, omdat ze daar gebruikt worden.

NetMain.cpp included vervolgens NetBuild.cpp, NetPrint.cpp en de NetZoek.cpp en gaat zijn gang.

De foutmelding die ik krijg gaat over elke methode die in Net.hpp gedeclareerd is, bv:
"/NetZoek.cpp:89: multiple definition of `Net::zoek(char*, char*)' "


C++: Net.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#ifndef _NET_HPP
#define _NET_HPP

#include <cstdio>
#include "List.hpp"
#include "Queue.hpp"

using namespace std;

class NetNode;
class NetLink;
class Net;
class TreeNode;

class NetNode
{
    friend class  Net;
    friend class  NetLink;

    char          *naam;
    List<NetLink> wegen;

                  NetNode(char *a)           {naam = a;};
    void          addLink(NetNode *, int);

public:
    void          print(ostream &);
};

class NetLink
{
     friend class  NetNode;
     friend class  Net;

     NetNode      *doel;
     int          kosten;

                  NetLink(NetNode *a, int b) {doel = a; kosten = b;};

public:
    void          print(ostream &);
};

class Net
{
    List<NetNode> nodes;
    NetNode       *findNode(char *);

public:
                  Net()                      {};
    void          addNode(char *);
    void          addLink(char *, char *, int);
    void          print(ostream &);
    TreeNode      *zoek(char *, char *);
};

class TreeNode
{
     friend class Net;

     NetNode      *netNode;
     TreeNode     *parent;

public:
                  TreeNode(NetNode *n, TreeNode *p) {netNode = n; parent = p;};
    void          print(ostream &);
    int           contains(NetNode *);
};
#endif  /* _NET_HPP */


C++: NetBuild.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "Net.hpp"
using namespace std;

char *kopie(char *s)
{
    return strcpy(new char[strlen(s)+1], s);
}

void NetNode::addLink(NetNode *nn, int w)
{
    wegen.add(new NetLink(nn,w));
}

void Net::addNode(char* s)
{
    nodes.add(new NetNode(kopie(s)));
}

void Net::addLink(char* a, char* b, int k)
{
    NetNode *na, *nb;
    na = findNode(a);
    nb = findNode(b);
    na->addLink(nb, k);
    nb->addLink(na, k);
}
NetNode* Net::findNode(char *s)
{
    for(All<NetNode>x(nodes); x.valid(); x.next())
    {
        if(strcmp(x.value()->naam, s) == 0)
        {
            return x.value();
        }
        return NULL;
    }
}


C++: NetPrint.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "Net.hpp"
using namespace std;

void NetNode::print(ostream& str)
{
    str << naam << endl;
}

void NetLink::print(ostream& str)
{
    str << kosten << ": ";
    doel->print(str);
}

void Net::print(ostream& str)
{
    for(All<NetNode> node(nodes); node.valid(); node.next())
    {
        node.value()->print(str);
        str << endl;
        for(All<NetLink> link(node.value()->wegen); link.valid(); link.next())
        {
            link.value()->print(str);
            str << endl;
        }
    }
}

void TreeNode::print(ostream& str)
{
    if(parent !=NULL)
    {
        parent->print(str);
        str << " - ";
    }
    netNode->print(str);
}


C++: NetZoek.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "Net.hpp"
using namespace std;

int TreeNode::contains(NetNode *nn)
{
    if(netNode == nn)
    {
        return 1;
    }
    if(parent != NULL)
    {
        return (parent->contains(nn));
    }
    return 0;
}
TreeNode *Net::zoek(char* s, char* g)
{
    NetNode *ns, *ng;
    TreeNode *tn, *ntn;
    Queue<TreeNode> queue(200);

    ns = findNode(s);
    ng = findNode(g);

    tn = new TreeNode(ns, NULL);
    queue.addAtBegin(tn);

    while(!queue.empty())
    {
        tn = queue.getFromBegin();
        if(tn->netNode == ng)
        {
            return tn;
        }
        for(All<NetLink> link(tn->netNode->wegen); link.valid(); link.next())
        {
            if(!tn->contains(link.value()->doel))
            {
                ntn = new TreeNode(link.value()->doel, tn);
                queue.addAtBegin(ntn);
            }
        }
    }
    return NULL;
}

Acties:
  • 0 Henk 'm!

  • Bob
  • Registratie: Mei 2005
  • Laatst online: 10:05

Bob

cpp files includen wordt zelden gedaan. Afhankelijk van je build systeem kan het dan fout gaan, wat nu waarschijnlijk gebeurt:

x.cpp wordt gecompileerd => definities worden geparsed
in y.cpp wordt x.cpp nog eens geinclude => definities van x.cpp worden nog eens geparsed => uh oh

Oplossing: in die main enkel headers includen, geen cpp files

[ Voor 10% gewijzigd door Bob op 08-04-2010 11:47 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Omdat ik dacht dat het probleem misschien zit in het meerdere keren includen van Net.hpp heb ik files NetBuild.cpp, NetPrint.cpp en de NetZoek.cpp in één file genaamd Net.cpp gezet en de oorspronkelijke files verwijderd.

Maar dat helpt helaas ook niet, ik heb nog steeds hetzelfde foutmeldingen ....

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

.edit: ah nvm, post niet goed gelezen.

[ Voor 85% gewijzigd door .oisyn op 08-04-2010 11:51 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bob schreef op donderdag 08 april 2010 @ 11:46:
cpp files includen wordt zelden gedaan.
Maar het zou dus wel kunnen?
Bob schreef op donderdag 08 april 2010 @ 11:46:
Oplossing: in die main enkel headers includen, geen cpp files
Held! Het werkt nu. Dank je wel. Ik heb gewoon alle implementaties ook in de Net.hpp gegooid, en de in de NetMain.cpp Net.hpp geincluded.


Maar ik zou nog steeds wel willen weten hoe ik .cpp files kan includen, omdat: stel ik maak een template queue.h in queue.cpp geef ik implementatie ervan. Volgende keer zou ik dat toch de .cpp file willen gebruiken en niet de .h file.

[ Voor 19% gewijzigd door Verwijderd op 08-04-2010 11:55 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 08 april 2010 @ 11:53:
Held! Het werkt nu. Dank je wel. Ik heb gewoon alle implementaties ook in de Net.hpp gegooid, en de in de NetMain.cpp Net.hpp geincluded.
Dat is natuurlijk ook een oplossing van niks. Main moet gewoon alleen Net.hpp includen, en als de rest van je cpp's gewoon in je project zitten dan compileren ze ook mee.
Maar ik zou nog steeds wel willen weten hoe ik .cpp files kan includen, omdat: stel ik maak een template queue.h in queue.cpp geef ik implementatie ervan. Volgende keer zou ik dat toch de .cpp file willen gebruiken en niet de .h file.
De fout die je maakt is dat de implementatie van die template in de cpp staat, waar hij niet hoort. Je kunt best de implementatie scheiden van de klassedefinitie, maar bottom line blijft de implementatie gewoon ook een header.

Ook wil je niet dat de overige code die ene header include. Typisch zal de header van de template klasse de implementatie zelf includen (want degene die de header include wil immers ook de implementatie weten anders kan ie 'm alsnog niet gebruiken)

[ Voor 12% gewijzigd door .oisyn op 08-04-2010 12:01 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 17:24

PoweRoy

funky!

Verwijderd schreef op donderdag 08 april 2010 @ 11:53:
[...]


Maar het zou dus wel kunnen?


[...]


Held! Het werkt nu. Dank je wel. Ik heb gewoon alle implementaties ook in de Net.hpp gegooid, en de in de NetMain.cpp Net.hpp geincluded.


Maar ik zou nog steeds wel willen weten hoe ik .cpp files kan includen, omdat: stel ik maak een template queue.h in queue.cpp geef ik implementatie ervan. Volgende keer zou ik dat toch de .cpp file willen gebruiken en niet de .h file.
Templates worden vooral alleen in headers gedefined (en geimplementeerd) vanwege de errors ;)

[This space is for rent]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
PoweRoy schreef op donderdag 08 april 2010 @ 12:00:
Templates worden vooral alleen in headers gedefined (en geimplementeerd) vanwege de errors ;)
Aha, thanks. Ik heb niets te willen dus :P

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Verwijderd schreef op donderdag 08 april 2010 @ 12:17:
[...]
Aha, thanks. Ik heb niets te willen dus :P
Je zou een compiler kunnen gebruiken die template export ondersteunt, maar die zijn er niet zo veel ( http://www.comeaucomputing.com/tryitout/ is een compiler die het wel ondersteunt )

De beste manier is inderdaad gewoon de template implementatie in je header file opnemen ( Eventueel door in je header file je CPP file te includen ).

[ Voor 12% gewijzigd door Woy op 08-04-2010 13:00 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

export is trouwens en-route om deprecated te worden, dus dat zou ik sowieso vergeten.
De beste manier is inderdaad gewoon de template implementatie in je header file opnemen ( Eventueel door in je header file je CPP file te includen ).
En dat is dus onhandig. Noem 'm *_impl.h oid, maar geen *.cpp, zodat je buildsysteem 'm ook niet gaat proberen afzonderlijk te compilen.

[ Voor 63% gewijzigd door .oisyn op 08-04-2010 13:04 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
.oisyn schreef op donderdag 08 april 2010 @ 13:03:
En dat is dus onhandig. Noem 'm *_impl.h oid, maar geen *.cpp, zodat je buildsysteem 'm ook niet gaat proberen afzonderlijk te compilen.
Ja je moet IDD wel zorgen dat je cpp niet gaat compilen, dus een .h extensie is inderdaad wat makkelijker. Het punt was echter dat je je implementatie nog best in een andere file kunt stoppen, maar dat je die dan alsnog gewoon moet includen in je header file.
export is trouwens en-route om deprecated te worden, dus dat zou ik sowieso vergeten.
Aangezien de meest gebruikte compilers export niet ondersteunen is het sowieso al nooit echt een goed plan geweest om het te gebruiken. Zeker aangezien de meerwaarde er niet heel erg groot van is.

[ Voor 23% gewijzigd door Woy op 08-04-2010 13:11 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Woy schreef op donderdag 08 april 2010 @ 13:09:
Het punt was echter dat je je implementatie nog best in een andere file kunt stoppen, maar dat je die dan alsnog gewoon moet includen in je header file.
Klopt, dat is wat ik eerder al zei in .oisyn in "\[C++] "multiple definition of" error" ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • planB
  • Registratie: Juli 2006
  • Laatst online: 00:08
laat maar, ik moet maar eens leren lezen ....

[ Voor 115% gewijzigd door planB op 08-04-2010 13:22 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt allemaal, probleem is opgelost en ik ben weer een stuk minder blondtdtd (hopelijk)

Ik heb nu:
List.hpp
Queue.hpp
Net.hpp
--> Net.cpp
--> NetMain.cpp

Net.hpp gebruikt zo wel list objecten als queue objecten, dus die worden daar geincluded.
NetMain.cpp gebruikt objecten die in Net.hpp gedeclareerd zijn, maar in Net.cpp uitgewerkt zijn.
Ik include gewoon de Net.hpp in de NetMain.cpp en alles gaat gewoon goed, compiler zoekt zelf de nodige implementatie van de methoden die in de Net.hpp staan.
Pagina: 1