Scholieren.com forum

Scholieren.com forum (https://forum.scholieren.com/index.php)
-   Huiswerkvragen: Exacte vakken (https://forum.scholieren.com/forumdisplay.php?f=17)
-   -   [C++] error: 'personen' was not declared in this scope. (https://forum.scholieren.com/showthread.php?t=1544950)

Sortjuh 17-02-2007 22:19

[C++] error: 'personen' was not declared in this scope.
 
Ik zit een beetje vast. Mijn compiler klaagt dat de variabele 'personen' niet gedeclareerd is, maar volgens mij is die dat juist wel. Enig idee?

Code:

//PersonenRegistratie.h

#ifndef PERSONENREGISTRATIE_H
#define PERSONENREGISTRATIE_H
#include "Persoon.h"
#include <list>

class PersonenRegistratie {
  private:
    list<Persoon *> personen;
  public:
    void persoonToevoegen();
};

#endif

PersonenRegistratie.cc ziet er zo uit (alleen de relevante dingen):

Code:

//PersonenRegistratie.cc
#include "PersonenRegistratie.h"

int main() {
  //Zooi declaraties
  personen = new list<Persoon *>;

  //Meer dingen
  exit(0);
}

exacte error:
Citaat:

PersonenRegistratie.cc: In function 'int main()':
PersonenRegistratie.cc:27: error: 'personen' was not declared in this scope

dutch gamer 18-02-2007 09:31

Ik heb weinig verstand van c++, maar moet je niet eerst aangeven in die "class PersonenRegistratie{" dat de functie int main() friendly is?

Zoniet: je kunt natuurlijk in int main() gewoon eerst zeggen van welk type "Personen" is en daarna pas de waarde eraan toekennen.

Bossen 18-02-2007 09:57

Ik heb weinig verstand van c++

WelVrolijk 18-02-2007 10:06

Zo te zien is "personen" een private member van de class PersonenRegistratie.

Dat member heb je dus juist private gemaakt, om te voorkomen dat andere functies (zoals main) er zomaar iets mee doen.

---------------

Zelfs als je het member "personen" public zou maken, dan kun je het nog steeds niet zomaar gebruiken in main.

"personen" is een member van de class PersonenRegistratie.

Dat betekent, dat elk object van het type PersonenRegistratie een member "personen" heeft.

Dus om te beginnen zul je een of meer objecten van de klasse PersonenRegistratie moeten maken (bijvoorbeeld mijnPersonenRegistratie, mijnAnderePersonenRegistratie, etc).

Vervolgens zul je dan ook aan moeten geven van *welke* PersonenRegistratie je de "personen" wilt benaderen.

Dan krijg je waarschijnlijk iets van de vorm
mijnPersonenRegistratie.personen
of
mijnAnderePersonenRegistratie.personen
.

---------

Maar waarschijnlijk wil je niet, dat de programmeurs (lees: de gebruikers van jouw class) dat doen.
Daarom heb je het member "personen" private gemaakt.

Als een programmeur iets met "personen" wil doen, zal hij/zij netjes gebruik moeten maken van de public function members (methods) die je speciaal daarvoor beschikbaar hebt gestelt.

=============================

De regel
personen = new list<Persoon *>;
klinkt overigens alsof je daarmee het private member "personen" wilt initialiseren.

Dat moet dan gebeuren in een function die onderdeel is van het de class PersonenRegistratie, en die automatisch wordt aangeroepen op het moment dat een nieuw object van die class wordt gemaakt.

Wellicht iets in de geest van
public PersonenRegistratie::PersonenRegistratie () {
personen = new list<Persoon *>;
}
of zo (De syntax moet je zelf even opzoeken, die weet ik niet uit mijn hoofd).

Rob 19-02-2007 03:54

Het is al opgelost. Maar waarom weet ik niet echt. (Ik was trouwens vergeten dat mijn vriendin nog ingelogd was. Oeps. :p)

Volgens mij kwam het hierdoor:

Origineel was dus PersonenRegistratie de entry point van mijn applicatie en PersonenRegistratie was niet ècht een class (er was alleen een methode main() en verder niets).
Na PersonenRegistratie tot class omgebouwd te hebben (main er dus uit, PersonenRegistratie een constructor gegeven) en een andere entry point voor de applicatie gemaakt te hebben, deed ie het wel.

Sortjuh 27-02-2007 03:20

Nu maar even een andere vraag.
Ik heb een vector met getallen er in genaamd *getallen en een int genaamd hoogsteGetal (staat geïnitialiseerd op 0). De vector moet met tellen beginnen bij 1.

Als ik een getal toevoeg met mijn methode, wordt het hoogste getal gelijk gezet aan getallen->back(), met één opgehoogd en toegevoegd mbv push_back: getallen->push_back(hoogsteGetal);.

Zo krijg je dus uiteindelijk een vector met als elementen 1, 2, 3, 4, 5, etc..

Allemaal leuk en aardig maar nou moet ik, wanneer ik een getal verwijder, het gat EERST opvullen met het getal dat daar eerst stond alvorens ik verder ga.

Stel dat ik dus een vector heb met de volgende elementen: 1, 2, 3, 4, 5, 6, 7.
Als ik 4 verwijder, heb ik dus dit: 1, 2, 3, 5, 6, 7. En wanneer ik weer een getal toe moet voegen, moet EERST 4 weer ingevuld worden en dan pas 8 (mits ik niet eerst iets verwijder).

Dus:
Het getal 1 zit op index 0
Het getal 2 zit op index 1
3 op 2

Hoe kan ik dit 't beste programmeren? Ik dacht dus eerst dat het het handigst is om zoiets als dit te doen:

Code:

for(int index = 0; index < getallen->size(); index++) {
  //als index++ niet gelijk is aan index + 2, klopt ie niet
  if(index++ != getallen->at(index+2)) {
    //Klopt niet, er moet een getal tussen hier
  }
}

Klopt dit een beetje, of is er een efficiëntere manier dan dit?

WelVrolijk 27-02-2007 08:04

Het idee lijkt mij goed, maar de code lijkt mij niet te kloppen.


Je wilt de plaats zoeken waar een getal moet worden ingevuld.
En je wilt zoeken vanaf het "begin" van de vector.
Als je daarbij de posities een voor een wilt checken, moet je de index slechts een keer per slag vergroten.

Je gebruikt echter twee keer index++:
Op de eerste regel *en* op de derde regel.
Daardoor zul je de helft van de posities overslaan.
Je moet binnen de loop dus *geen* gebruik maken van index++ of ++index.
(Overigens vergelijk je volgens mij op dit moment bij de eerste slag de index 0 met het getal op positie 3, wat 4 is of hoger of buiten bereik...).


Je hebt geconstateerd dat --voor het deel van de vector dat nog *wel* klopt-- op elke positie een getal staat dat 1 groter is dan de index.
Dan zou je dus bijvoorbeeld index+1 kunnen vergelijken met getallen-->at(index).

Sortjuh 27-02-2007 13:02

Citaat:

WelVrolijk schreef op 27-02-2007 @ 09:04 :
Het idee lijkt mij goed, maar de code lijkt mij niet te kloppen.


Je wilt de plaats zoeken waar een getal moet worden ingevuld.
En je wilt zoeken vanaf het "begin" van de vector.
Als je daarbij de posities een voor een wilt checken, moet je de index slechts een keer per slag vergroten.

Je gebruikt echter twee keer index++:
Op de eerste regel *en* op de derde regel.
Daardoor zul je de helft van de posities overslaan.
Je moet binnen de loop dus *geen* gebruik maken van index++ of ++index.
(Overigens vergelijk je volgens mij op dit moment bij de eerste slag de index 0 met het getal op positie 3, wat 4 is of hoger of buiten bereik...).


Je hebt geconstateerd dat --voor het deel van de vector dat nog *wel* klopt-- op elke positie een getal staat dat 1 groter is dan de index.
Dan zou je dus bijvoorbeeld index+1 kunnen vergelijken met getallen-->at(index).

Ja, de code heb ik dan ook maar even vlug geschreven. ;p

Nu je het zegt verhoog ik index inderdaad twee keer, even vergetend dat index++ je counter permanent verhoogd en dat het niet iets is dat zich 'reset' als het ware. Ik weet niet waarom ik dat dacht, maar ik dacht het.

Maar dan weet ik nu waarschijnlijk wel hoe ik 't op moet lossen. :D

Sortjuh 02-03-2007 19:58

Is gelukt.

Nu heb ik weer iets anders: het overloaden van de << operator.

Ik heb een class Dierentuin met daarin een map waarin werknevers opgeslagen worden. Er is een functie Dierentuin::overzichtWerknemers() die over de map itereert en alle data op het scherm tovert.

Er is ook een Main file van waaruit menuopties gekozen kunnen worden.

Nu moet ik de Main file zo aanpassen dat cout << *artis werkt. De code is als volgt:

Code:

//Main.cc
#include <iostream>
#include "Dierentuin.h"

int main() {
  Dierentuin *artis = new Dierentuin("Artis");
  cout << *artis;
}

Nu heb ik het volgende gedaan om << te overloaden:

Code:

//Dierentuin.h

class Dierentuin {
  friend ostream& operator <<(ostream &out, const Dierentuin &d);
  public:
    //
    void overzichtWerknemers();
  private:
    //
    map<int, Werknemer *> * werknemers;
}

Code:

//Dierentuin.cc
Dierentuin::Dierentuin(string naam) {
  werknemers = new map<int, Werknemer *>;
}

//Code

void Dierentuin::overzichtWerknemers() {
  cout << "Overzicht van de werknemers\n";
  for(map<int, Werknemer *>::iterator iter = werknemers->begin(); iter!= werknemers->end(); ++iter) {
    cout << iter->first << "\t";
    iter->second->drukaf();
  }
}

//Meer code

ostream& operator <<(ostream& out, Dierentuin &d) {
  out <<d.overzichtWerknemers();
  return out;
}

Verder is de methode drukaf() virtueel gedeclareerd in de Werknemer basis class en dus geïmplementeerd in de subclasses van Werknemer (in dit geval Administrateur, Oppasser en Manager). Van alle methoden is de terugkeer een void.

Ik krijg de volgende (samengevatte) compilererror:
Dierentuin.cc:336: error: no match for 'operator<<' in 'out << ((Dierentuin*)d)->Dierentuin::overzichtWerknemers();

Als ik regel 336 vervang door:

out << Dierentuin::overzichtWerknemers();

zegt ie:

"cannot call member function 'void Dierentuin::overzichtWerknemers()' without object".

M.A.W.: Ik zit dus een beetje vast. Enig idee hoe ik dit kan wijzigen zodat die wel netjes de output laat zien met de huidige structuur?

WelVrolijk 02-03-2007 22:42

In de regel
out <<d.overzichtWerknemers();
lijkt het alsof je een void naar de outstream wilt sturen.

Kun je niet gewoon de code die je in overzichtWerknemers hebt staan plaatsen in de operator?

Of alternatief:
Definieer de functie overzichtWerknemers zo, dat hij een string oplevert.

-------------------

Even een opmerking mbt de functionaliteit:

Blijkbaar hebben dierentuinen een naam.

Dan verwacht ik in de outstream toch op zijn minst de naam van de dierentuin te zien. Maar die sla je blijkbaar over ...

-------------------

En nog iets:

Ik kan niet zien wat drukaf() doet, maar ik neem aan dat die de werknemer naar de standaard output afdrukt.
Dat is in ieder geval te hopen, want vlak daarvoor stuur je blijkbaar het nummer van de werknemer naar de standaard output. Het zou slordig zijn als de (informatie over) de werknemer vervolgens in een andere output stream terecht zou komen.

Bij het overloaden van de << operator zou je echter naar de opgegeven outputstream moeten schrijven, en niet naar de standaard stream ...
Op die manier krijg je waarschijnlijk iets wat *alleen* goed werkt zolang je schrijft naar cout ...

Sortjuh 02-03-2007 23:26

Citaat:

WelVrolijk schreef op 02-03-2007 @ 23:42 :
In de regel
out <<d.overzichtWerknemers();
lijkt het alsof je een void naar de outstream wilt sturen.

Kun je niet gewoon de code die je in overzichtWerknemers hebt staan plaatsen in de operator?

Of alternatief:
Definieer de functie overzichtWerknemers zo, dat hij een string oplevert.


Dat eerste heb ik al geprobeerd, maar dat werkte niet echt lekker. De tweede probeer ik nu...

Nu krijg ik wel een string result, maar nog steeds een compiler error. Namelijk in Main.cc (waar cout << *artis wordt aangeroepen):
undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> > &, Dierentuin const&)`

Citaat:


Even een opmerking mbt de functionaliteit:

Blijkbaar hebben dierentuinen een naam.

Dan verwacht ik in de outstream toch op zijn minst de naam van de dierentuin te zien. Maar die sla je blijkbaar over ...

Ja, ach. Er is maar een dierentuin en de opdracht zegt dat ik alleen maar het overzicht van de werknemers mee hpoef te geven.

Citaat:

En nog iets:

Ik kan niet zien wat drukaf() doet, maar ik neem aan dat die de werknemer naar de standaard output afdrukt.
Dat is in ieder geval te hopen, want vlak daarvoor stuur je blijkbaar het nummer van de werknemer naar de standaard output. Het zou slordig zijn als de (informatie over) de werknemer vervolgens in een andere output stream terecht zou komen.

Bij het overloaden van de << operator zou je echter naar de opgegeven outputstream moeten schrijven, en niet naar de standaard stream ...
Op die manier krijg je waarschijnlijk iets wat *alleen* goed werkt zolang je schrijft naar cout ... [/B]
drukaf() was niets meer dan:
cout << naam << "\t" << leeftijd;

Die outputte de info naar de standaard output (dus naar de console). Nu laat ik die methode een string terugkeren.

En het is ook de bedoeling dat alleen iets als cout << werkt.

WelVrolijk 03-03-2007 10:00

Citaat:

Sortjuh schreef op 03-03-2007 @ 00:26 :
Dat eerste heb ik al geprobeerd, maar dat werkte niet echt lekker. De tweede probeer ik nu...

Nu krijg ik wel een string result, maar nog steeds een compiler error. Namelijk in Main.cc (waar cout << *artis wordt aangeroepen):
undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> > &, Dierentuin const&)`

Als het goed is, definieer je die in dit stukje:

ostream& operator <<(ostream& out, Dierentuin &d) {
out <<d.overzichtWerknemers();
return out;
}


d.overzichtWerknemers() levert nu een string, dus out <<d.overzichtWerknemers(); zou nu dus gewoon moeten werken.

Wellicht is dat const een probleem? Momenteel staat dat *wel* in je declaratie, maar *niet* in je definitie meen ik.

Sortjuh 03-03-2007 15:48

Dat const gaf inderdaad een probleem, maar ik heb niet echt door waarom. Ik moest const uit de definitie verwijderen en toen deed ie 't. Raar, want in de voorbeelden die ik zag, moest ie er wel bij. Ik vind het altijd zo jammer als ik een fout oplos en niet echt snap waarom het werkt.

Maar hij doet 't nu. :p


Alle tijden zijn GMT +1. Het is nu 08:28.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.