[C++] variabel overhevelen

Pagina: 1
Acties:

  • madwoody
  • Registratie: Augustus 2001
  • Laatst online: 29-06 10:53

madwoody

Connection reset by ME

Topicstarter
Ik had eerst in borland c++ builder 5.0 dat gewoon bestond uit een cpp file en een header file voor het gemak even main.cpp en main.h genoemd. In de header file staat een Class die ik in diezelfde header file declareer. Deze class wordt in een procdure gevuld.

Alles goed en wel totdat ik besloot een tweede cpp en header file aan te maken met daarin de de veel gebruikte procedures. Ik noem deze global.cpp en global.h. De procedure die de Class vult stop ik in global.cpp en de Class stop ik in de global.h. In main.cpp include ik global.h

Nu is het probleem dat de gegevens die ik in de Class laad in global.cpp wel verder door andere procedures die in global.cpp zijn uit te lezen maar zodra ik de Class vanuit een procedure in main.cpp wil gebruiken staat er helemaal niks in deze procedure 8)7

Wat doe ik fout of probeer ik iets wat helemaal niet kan :?

Specs: Game/LANBak FTP/Gameserver Unix Server Visit http://www.gamesfm.nl


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-08 15:58
:?
Ik heb even moeite met volgen. ;)

In de main.h staat je class bv:
code:
1
2
3
4
5
6
7
class MyClass
{
  private:
    int a;
  public:
     int getValue();
};

en in main.cpp staat de class dan uitgewerkt:
code:
1
2
3
4
int MyClass::getValue()
{
  return a;
}

Althans, dit is de manier waarop je het zou moeten doen.

Hoe roep je die functies vanuit die global.cpp aan enzo? Dus, post eens wat relevante code. (Ga niet al je code posten, want dat schrikt de mensen toch maar af...)

https://fgheysels.github.io/


  • madwoody
  • Registratie: Augustus 2001
  • Laatst online: 29-06 10:53

madwoody

Connection reset by ME

Topicstarter
global.h
code:
1
2
3
4
5
6
7
8
9
10
11
Class CDirInfo
{
  public:
  AnsiString    Data;                     // Directory with the data files
  AnsiString    CharacterDir;             // Directory with the character actions&animations
  AnsiString    LevelDir;                 // Directory with the map files
  AnsiString    FontDir;                  // Directory with Font files
  AnsiString    SoundDir;                 // Directory with Sound files
};

CDirInfo    DirInfo;



global.cpp
code:
1
2
3
4
5
6
void LoadDirInfo()
{
  DirInfo.Data="c:\project\data";
  DirInfo.CharacterDir="c:\project\chars";
  enz...
}


Global.h staat gedeclareerd in de header file van m'n hoofdsource. In main.h dus.


main.cpp:
code:
1
2
3
4
5
6
void testje()
{
  LoadDirInfo();    
  ShowMessage(DirInfo.Data);
  ShowMessage(DirInfo.CharacterDir);
}


Waar ShowMessage staat, staat normaal natuurlijk een procedure die er iets mee doet maar om te weten wat er dus in die variablen staat heb ik dus ShowMessage gebruikt.

Als ik dus in main.cpp die DirInfo.Data en DirInfo.CharacterDir uitlees staat er niks in :(

Als ik de ShowMessage in de procedure LoadDirInfo onderaan plaats staat er wel in wat ik erin heb gezet :?

Specs: Game/LANBak FTP/Gameserver Unix Server Visit http://www.gamesfm.nl


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-08 15:58
Waarom doe je het niet als volgt:
Ipv een 'gewone' functie LoadDirInfo te maken, maak je een memberfunctie van CDirInfo die die functionaliteit gaat gaan verzorgen. Zo dus:
code:
1
2
3
4
5
6
7
8
9
10
class CDirInfo
{
   private:
      AnsiString data;
      AnsiString charachterdir;
      ....
   public:
      void LoadDirInfo(AnsiString directory);
      AnsiString getData();
};

en dan werk je die LoadDirInfo functie uit:
code:
1
2
3
4
5
6
7
8
9
10
void CDirInfo::LoadDirInfo(AnsiString directory)
{
   Data = directory;
   ....
}

AnsiString CDirInfo::getData()
{
   return Data;
}

(Dit kan je trouwens ook in de constructor opnemen [de LoadDir functie dan, niet die getData() ;) ).
Trouwens, ik zie dat je in CDirInfo alle members public maakt.... Het beste is om zo weinig mogelijk membervariablen public te maken.
Je string die je aan DirInfo.Data assigned klopt eigenlijk ook niet, je moet die backslashes escapen:
code:
1
"c:\\project\\data";


En in main.cpp doe je dan:
code:
1
2
3
4
5
void testje()
{
   DirInfo.LoadDirInfo(...);
   ShowMessage (DirInfo.getData());
}

https://fgheysels.github.io/


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Je hebt een globale variable DirInfo en die structuur heb je niet helemaal goed opgezet. En globale variablen zijn niet echt heel netjes in een programma en dienen dan ook zoveel als mogelijk vermeden te worden. whoami heeft een veel betere en nettere oplossing gegeven die ik je ook zou adviseren.

Maar om even terug te komen waarom jouw structuur niet werkte is omdat je meerdere variablen DirInfo hebt. Voor elke include 1. En die wijzen niet naar hetzelfde stuk geheugen.
Global.h
code:
1
extern CDirInfo    DirInfo;

Global.cpp
code:
1
CDirInfo    DirInfo;

zou wel moeten werken.
Of helemaal geen globale variable DirInfo, maar 1tje locaal in Main en die dan meegeven aan LoadDirInfo
code:
1
  LoadDirInfo(DirInfo);

We adore chaos because we like to restore order - M.C. Escher


  • madwoody
  • Registratie: Augustus 2001
  • Laatst online: 29-06 10:53

madwoody

Connection reset by ME

Topicstarter
Als ik het op de manier van <i>whoami</i> doe hoe kan ik er dan weer naartoe schrijven? Want in m'n programma worden de waardes van deze class op het scherm gezet waarna je ze kan editen. Moet ik dat dan zo doen?

global.h
code:
1
2
3
4
5
6
7
8
9
10
class CDirInfo
{
   private:
      AnsiString data;
      AnsiString charachterdir;
      ....
   public:
      void LoadDirInfo(AnsiString directory);
      AnsiString putData();
};


global.cpp
code:
1
2
3
4
void CDirInfo::putData(AnsiString a)
{
   Data=a;
}

Wordt m'n class dan niet een beetje lang als ik dat met elke variabel in de class moet doen? Is de oplossing van LordLarry dan niet sneller? Als dat andere netter is doe ik dat denk ik.

[ Voor 0% gewijzigd door madwoody op 11-11-2002 02:09 . Reden: foutje ]

Specs: Game/LANBak FTP/Gameserver Unix Server Visit http://www.gamesfm.nl


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

titel fixed
als het toch allemaal public members zijn en zonder constructors/destructors, waarom dan niet gewoon een struct?

Anyway, encapsulatie en data hiding zijn belangrijke dingen in OO. Member variabelen zijn over het algemeen private, en kunnen mbv getters en setters (gewoon memberfuncties) opgehaald of gewijzigd worden. In die functies kun je dan weer bijvoorbeeld foutafhandelijk doen voor ongeldige waarden. Je code wordt veel aanpasbaarder op die manier.

Maar dit was overigens niet wat whoami bedoelde. Wat hij bedoelde is dat je de instantie van CDirInfo niet globaal moest maken, maar in de functie LoadDirInfo () een referentie mee moet geven waar het resultaat in moet komen te staan:

C++:
1
2
3
4
void LoadDirInfo (CDirInfo & info)
{
    ...
}


nu kun je de main () functie een instantie aan laten maken en die meegeven. Globale variabelen worden over het algemeen (niet altijd dus) gezien als een slecthe stijl

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: 24-08 22:38
De reden dat het niet werkt is dat je met verschillende variabelen werkt, terwijl jij denkt dat het 1 globale is. ( Variabelen in c++ hebben standaard static ( lokaal voor de compilatieunit ) linking. ( compilatieunit = cpp file in jouw geval )

Dus :

global.h
C++:
1
CDirInfo    DirInfo;


is identiek aan :
C++:
1
static CDirInfo    DirInfo;

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.


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-08 15:58
[nohtml]
.oisyn schreef op 11 November 2002 @ 02:46:

Anyway, encapsulatie en data hiding zijn belangrijke dingen in OO. Member variabelen zijn over het algemeen private, en kunnen mbv getters en setters (gewoon memberfuncties) opgehaald of gewijzigd worden. In die functies kun je dan weer bijvoorbeeld foutafhandelijk doen voor ongeldige waarden. Je code wordt veel aanpasbaarder op die manier.

Maar dit was overigens niet wat whoami bedoelde.
Toch ook wel hoor. :Y)

Je maakt het best geen enkele data member in je class public. De enige manier waarop je ze zou mogen accessen is via een property of via een get/set functie. Misschien dat het daardoor iets trager wordt, maar ik denk niet dat het verschil meetbaar is. Als je het op die manier doet, dan kan jij bepalen welke member-variablen er toegankelijk zijn en of ze al dan niet read-only zijn.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-08 15:58
farlane schreef op 11 november 2002 @ 09:33:
De reden dat het niet werkt is dat je met verschillende variabelen werkt, terwijl jij denkt dat het 1 globale is. ( Variabelen in c++ hebben standaard static ( lokaal voor de compilatieunit ) linking. ( compilatieunit = cpp file in jouw geval )

Dus :

global.h
C++:
1
CDirInfo    DirInfo;


is identiek aan :
C++:
1
static CDirInfo    DirInfo;


Hmm, ik durf me er niet aan te wagen in de situatie van een global maar als je een variable declareert in C++ is dat gelijk aan een automatic, en niet aan een static.
Een auto variable definieert een variable met een locale scope.
Als je dus:
C++:
1
2
3
4
void Test()
{
  auto int Index = 0;
}

schrijft, is dat hetzelfde als:
C++:
1
2
3
4
void Test()
{
  int Index = 0;
}

maar niet als
C++:
1
2
3
4
void Test()
{
  static int Index = 0;
}


Bij de static variable, wordt Index slechts 1x geinitialiseerd, nl. bij de eerste keer dat de functie test geaccessed wordt.
Stel dat in de functie Test Index iedere keer geincrementeerd wordt:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
   for (int i = 0; i < 5; i++)
   {
       StaticTest();
       AutoTest();
   }
}

void StaticTest()
{
  static int Index = 0;
  Index++;
  cout << Index;
}

void AutoTest()
{
   int Index = 0;
   Index++;
   cout << Index;
}


Dan zal de output als volgt zijn:
code:
1
2
3
4
5
6
7
8
9
10
1
1
2
1
3
1
4
1
5
1

Maw, de static behoudt zijn vroegere waarde, maar de 'auto' niet, de automatic variable wordt iedere keer opnieuw geinitialiseerd, terwijl de static slechts 1x geinitialiseerd wordt.

https://fgheysels.github.io/


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 24-08 22:38
deed whoami wat testjes:

[...]


Hmm, ik durf me er niet aan te wagen in de situatie van een global maar als je een variable declareert in C++ is dat gelijk aan een automatic, en niet aan een static.
Een auto variable definieert een variable met een locale scope.
Mijn verhaal geldt idd voor variabelen die in de global scope van de compilatieunit zijn gedeclareerd. Static heeft in dat geval ook een andere betekenis ( 'scope' ) dan wanneer je een static variabele in een functie declareert, of in een klasse ( 'lifetime' ).

Ik zie trouwens dat ik wel een fout heb gemaakt. Default hebben globale variabelen external linkage, dwz ze kunnen vanuit andere units 'gezien' worden.
The "static storage class", with specifiers "static" and "extern", in which variables come into existence (at least conceptually) when the program begins to execute and remain in existence for the duration of the program's execution time. This is the default storage class for global variables.
Applying the "static" specifier explicitly to a global variable gives it "internal linkage", i.e., this prevents the variable from being used by any function not defined in the current file. However, this use of the "static" specifier has been deprecated in favor of placing such a variable in the unnamed namespace of the file to which its use is to be limited.

Applying the "static" specifier to a local variable in a function means that the value of that variable will be retained from one call of that function to the next.

Global variables are assumed to have the "extern" specifier by default and hence have "external linkage", which means they can be seen and used ("linked to", if you like) by code in other files. Applying it explicitly to variable declaration means that the definition of that variable is found either later in the current file, or in another file. This implies that a variable cannot be defined/initialized in an "extern" declaration.
[edit]
Waarom deze meneer geen linker fout krijgt is me eigenlijk niet helemaal duidelijk ... misschien andere namespaces ?

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: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker



mijn fout... khad je post vluchtig door gelezen en ik had geen zin om omhoog te scrollen toen de TS het over jouw post had ;)
whoami schreef op 11 november 2002 @ 10:10:
Hmm, ik durf me er niet aan te wagen in de situatie van een global maar als je een variable declareert in C++ is dat gelijk aan een automatic, en niet aan een static.
[/nohtml]

Nu heb je het over lokale variabelen. Als je een globale variabele (of functie) static maakt, dan is die alleen zichtbaar in die sourcefile waarin ie gedefinieerd is. Als een andere sourcefile die variabele dan als extern declareert dan zal de linker m ook niet kunnen vinden (en op die manier krijg je dus ook geen last van nameclashes). Hetzelfde geldt overigens ook voor anonymous namespaces

Aan de andere kant, volgens mij mag de compiler m helemaal niet default static maken... je hoort gewoon een linker error te krijgen (2 dezelfde symbols). En als hij niet static wordt gemaakt dan controleert Borland's linker daar blijkbaar niet op, wat me erg slecht lijkt.

.edit: deze post deed ik al voor farlane's laatste post, maar toen kon ik niet posten door een database error... heb m'n pc aan laten staan en weggegaan, en toen ik terug was heb ik op post geramd :P

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.


  • madwoody
  • Registratie: Augustus 2001
  • Laatst online: 29-06 10:53

madwoody

Connection reset by ME

Topicstarter
Waarom deze meneer geen linker fout krijgt is me eigenlijk niet helemaal duidelijk ... misschien andere namespaces ?
Uhm, is dat die linker warning ? :)

Specs: Game/LANBak FTP/Gameserver Unix Server Visit http://www.gamesfm.nl


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

warnings moet je serieus nemen, ondanks dat het wel compileert! (Treat warnings as errors is altijd een goede compileroptie). Als je je erin had verdiept had je ook meteen geweten waarom het niet werkte :)

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.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
farlane schreef op 11 November 2002 @ 15:28:
[edit]
Waarom deze meneer geen linker fout krijgt is me eigenlijk niet helemaal duidelijk ... misschien andere namespaces ?
ODR overtreden is UB.

One Definition Rule, Undefined Behavior

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

Pagina: 1