[c++] Recursief includen

Pagina: 1
Acties:

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Hoi

Even voor UTFS geroepen wordt:

Dit topic ([rml][ C++] include-probleem[/rml]) heb ik al gelezen nav queries als deze: "recursieve include" (zonder quotes dan) en dergelijke.

Ik zit met het probleem dat ik een brok assembler code wil schematiseren. Hiervoor gebruik ik 2 klassen, een 'opcode' en een 'functie' (niet zeiken over de naamgeving, ik kies het *niet*).

functie bezit een aantal opcodes (en vormt dus een container) en heeft dus kennis nodig van 'opcode'. nodig. Echter wil ik in opcode ook een pointer naar de de functie waar hij in ligt.

Nu stond er in de draad hierboven dat je het op kunt lossen door allebei in 1 header te kwakken (ik gebruik standaard al de #ifndef x ... #define x .... code .... #endif methode ).

Nu werkt het als volgt niet (even de niet relevante code ge-dd'ed):
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef FUNCTION_H_
#define FUNCTION_H_

class Command{
public:
    Command();
private:
    Function *parent;
    
};


class Function: public Command {
    
public:
     Function(char *name);
};


#endif /*FUNCTION_H_*/


Dit doe ik op OS X met GCC (onder Eclipse+CDT). Puur gcc werkt ook niet:
code:
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
bigmac:~/Documents/workspace/disassemblyCycleCounter/Debug boudewijn$ make -k all
Building file: ../command.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -ocommand.o ../command.cpp
../function.h:14: error: ISO C++ forbids declaration of 'Function' with no type
../function.h:14: error: expected ';' before '*' token
make: *** [command.o] Error 1
Building file: ../dCC.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -odCC.o ../dCC.cpp
../function.h:14: error: ISO C++ forbids declaration of 'Function' with no type
../function.h:14: error: expected ';' before '*' token
../dCC.cpp: In function 'int main(int, const char**)':
../dCC.cpp:28: warning: unused variable 'mainFunction'
make: *** [dCC.o] Error 1
Building file: ../function.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -ofunction.o ../function.cpp
../function.h:14: error: ISO C++ forbids declaration of 'Function' with no type
../function.h:14: error: expected ';' before '*' token
make: *** [function.o] Error 1
Building file: ../inputReader.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -oinputReader.o ../inputReader.cpp
Finished building: ../inputReader.cpp
 
Building file: ../outputWriter.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -ooutputWriter.o ../outputWriter.cpp
Finished building: ../outputWriter.cpp
 
make: Target `all' not remade because of errors.


Hoe kan ik dit het netste tackelen?

  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

Dat staat in de foutmelding :? Al je functies / members die je in de header zet bevatten geen returntype.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21:20
Je ontwerp is fout : Function is een Command, en Command heeft een 'Function' member. Dat kan niet kloppen.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

voor jou en voor het nageslacht:

- declaratie van x: aangeven dat x bestaat (x is ERGENS gedefinieerd/geimplementeerd)
de declaratie geeft overigens enkel de vorm aan
- definitie van x: de implementatie van x geven

daarom:
- in de header (1 header per class liefst) declareer je alles wat je ergens anders wil kunnen gebruiken
- in de cpp file definieer je de overeenkomstige header.

wat doet je compiler (heel ruw geschetst):
maakt een obj. bestand aan per cpp bestand met:
- welke declaraties deze obj.file nodig heeft (moet geimporteerd worden)
- welke declaraties deze zelf bevat/definieert/invult

je linker tenslotte:
- zorgt dat de niet ingevulde declaraties uit de ene obj.file (import nodig) ingevuld raken met de definities van de andere obj.files
- bekijkt bijgevolg alle obj.files en maakt er 1 executable van. (niet gelet op dynamic linking)

de #include opdracht copy-paste bij wijze van spreken zomaar het gespecifieerde bestand op de plaats van de #include-opdracht.
Dit zorgt dat de compiler tijdens compilatie van het bestand weet: "ergens" is x gedefinieerd en
het ziet er zo uit (volgens de vorm). Zo kan de compiler syntax en oproepen controleren op vorm en juistheid. (En natuurlijk ook aangeven dat de linker de juiste links hoeft te leggen)

------------
edit: en om ook iets concreter op je vraag te antwoorden:
als 2 klassen elkaar nodig hebben kun je dit doen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef __MYCLASS1
#define __MYCLASS1

#include "myclass2.h"

#ifndef __MYCLASS2__DECLARED
class MyClass2;
#endif

class MyClass1
{
public:
   MyClass1();
};

#define __MYCLASS1__DECLARED
#endif


C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef __MYCLASS2
#define __MYCLASS2

#include "myclass1.h"

#ifndef __MYCLASS1__DECLARED
class MyClass1;
#endif

class MyClass2
{
public:
   MyClass2();
};

#define __MYCLASS2__DECLARED
#endif


Of er ook een mooiere oplossing is weet'k niet meteen, maar dat kun je zeker op internet vinden
(misschien eerder zoeken op "cross include" of zoiets)

[ Voor 27% gewijzigd door H!GHGuY op 02-06-2006 17:48 ]

ASSUME makes an ASS out of U and ME


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:22
Je mist een forward declaration van Function. Zet eens "class Function;' voor je definitie van Command.

Het helpt trouwens niet dat je een heel buildlog post, waarin allerlei bestanden en regelnummers genoemd worden die niet corresponderen met de voorbeeldcode die je geeft. Bovendien zijn al die andere meldingen van make (gmake?) niet relevant. Volgende keer een wat duidelijkere foutmelding alsjeblieft!

[ Voor 14% gewijzigd door Soultaker op 02-06-2006 17:38 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12-2025
farlane schreef op vrijdag 02 juni 2006 @ 17:20:
Je ontwerp is fout : Function is een Command, en Command heeft een 'Function' member. Dat kan niet kloppen.
Dat staat er ook niet. Comamnd heeft een Function* member. Essentieel verschil

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

MSalters schreef op zaterdag 03 juni 2006 @ 14:47:
[...]

Dat staat er ook niet. Comamnd heeft een Function* member. Essentieel verschil
zelfs dan nog...

als hij zegt dat Command een opcode voorstelt
en dat een opcode moet weten in welke functie ie staat (Function* dus)
lijkt het me niet logisch dat een functie afleidt van een opcode.

Ik zou dan eerder geneigd te zijn om een "Call"-opcode te maken die een functie als member heeft waarnaar hij kan jumpen.

ASSUME makes an ASS out of U and ME


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12-2025
Sowieso moet hij z'n opcode class Opcode noemen, anders blijft het inderdaad kwakkelen.
Ik denk dat het belangrijkste is dat hij afmoet van de illusie dat opcodes iets van functiea af moeten weten. Opcodes bestaan niet buiten functies. Alle code die iets met opcodes doet, doet dat met een opcode uit een functie.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

HIGHGuY schreef op vrijdag 02 juni 2006 @ 17:37:
------------
edit: en om ook iets concreter op je vraag te antwoorden:
als 2 klassen elkaar nodig hebben kun je dit doen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef __MYCLASS1
#define __MYCLASS1

#include "myclass2.h"

#ifndef __MYCLASS2__DECLARED
class MyClass2;
#endif

class MyClass1
{
public:
   MyClass1();
};

#define __MYCLASS1__DECLARED
#endif


C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef __MYCLASS2
#define __MYCLASS2

#include "myclass1.h"

#ifndef __MYCLASS1__DECLARED
class MyClass1;
#endif

class MyClass2
{
public:
   MyClass2();
};

#define __MYCLASS2__DECLARED
#endif
Allereerst: gebruik geen leading underscores, die zijn gereserveerd voor de implementation en kunnen dus mogelijk conflicteren.
Ten tweede, die DECLARED dingen zijn een beetje pointless. Als je van een class/struct alleen een naam nodig hebt, declare 'm dan gewoon en include 'm niet. In je voorbeeld hebben geen van beide classes elkaar echt nodig, maar stel dat MyClass1 een pointer naar MyClass2 nodig heeft. Dan declare je MyClass2 gewoon altijd voor MyClass1 maar include je 'm nooit. Dat mag de sourcefile doen die daadwerkelijk iets met die MyClass2 pointer doet.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef MYCLASS1_H
#define MYCLASS1_H

class MyClass2;

class MyClass1
{
public:
    MyClass2 * GetPtr();
};

#endif


Als je 'm echter nodig hebt voor de definitie van je class, dan heb je natuurlijk geen andere keuze dan 'm gewoon te includen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef MYCLASS2_H
#define MYCLASS2_H

#include "MyClass1.h"

class MyClass2 : public MyClass1
{
public:
    // ...
};

#endif


Als je dit patroon altijd aanhoudt zul je zien dat je nooit in de problemen komt, en je compile dependencies bovendien zo laag mogelijk blijven (als de definitie van MyClass2 wijzigt hoeven de sourcefiles die slechts gebruik maken van MyClass1 niet opnieuw gecompileerd te worden).

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.


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

blijkbaar was er dus toch een mooiere oplossing ;)

ASSUME makes an ASS out of U and ME


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21:20
MSalters schreef op zaterdag 03 juni 2006 @ 14:47:
Dat staat er ook niet. Comamnd heeft een Function* member. Essentieel verschil
Essientieel verschil voor de code misschien maar niet voor het ontwerp. Als een parent van een class een member nodig heeft met als type een (pointer naar) child class dan klopt er iets niet.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik vind dat een beetje kort door de bocht om dat zo maar te stellen. Er zijn legio voorbeelden te verzinnen waarbij dat wel zo werkt. Ik zal even aftrappen: een Component class dat een UI component voorstelt, en een Container class die afleidt van Component (het is immers ook een component). De Component zet je in een Container, dus elke Component heeft een pointer naar z'n parent: een Container.

C++:
1
2
3
4
5
6
7
8
9
10
11
class Container;

class Component
{
    Container * GetParent();
};

class Container : public Component
{
    void AddComponent(Component *);
};

[ Voor 22% gewijzigd door .oisyn op 08-06-2006 14:20 ]

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.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21:20
Laten we het dan zo zeggen, als je ontwerp op iets dergelijks terecht komt moet je jezelf afvragen of het wel het handigst is om dat zo te doen.

Mbt op jouw specifieke voorbeeld, ik ben het niet eens met jouw beslissing dat een container een UI component is. Ik zou het logischer vinden om een UI component een container te laten zijn.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarom? Je kunt een button (component) in een panel (container) stoppen. Je kunt ook een panel (als component) in een andere panel stoppen. Maar je kunt niets in een button stoppen (het is immers geen container)

Kijk anders eens naar de java AWT class hierarchy, die zit precies hetzelfde inelkaar

[ Voor 14% gewijzigd door .oisyn op 08-06-2006 14:17 ]

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.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21:20
.oisyn schreef op donderdag 08 juni 2006 @ 14:16:
Waarom? Je kunt een button (component) in een panel (container) stoppen. Je kunt ook een panel (als component) in een andere panel stoppen. Maar je kunt niets in een button stoppen (het is immers geen container)
Gevoelsmatig denk ik. Denk dat ik dan een verschil zou gaan maken tussen een Component en een ContainerComponent of zoiets. Heb er niet al te lang over nagedacht dus shoot me if im wrong. :)

( Tis natuurlijk maar zo een voorbeeld, misschien dat in een andere situatie je wel op een dergelijks iets terecht komt )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1