Gå til innhold

Kalle en funksjon i en annen klasse.


Anbefalte innlegg

Jeg har main-fil, en .h/.cpp fil som heter r2d290, en som heter Skybert, og en som heter people.

 

r2d290 og Skybert arver fra people.

 

Jeg skal kaste ball mellom r2d290 og Skybert. Det jeg har fått til er å, fra main, med r2d290 om å kaste en ball til Skybert. Det gjør jeg på følgende måte:

 

r2d290* bruker1 = new r2d290("usr_r2d290"); //Denne lager objektet på heap
Skybert* bruker2 = new Skybert("usr_skybert");
[...]
bruker1->throwBall( bruker2 );

 

throwBall i r2d290 ser slik ut:

void r2d290::throwBall( People* anotherDude )
{
 Ball* ball = ballContainer[0];//check om den inneholder en ball før dette
 ballContainer.erase(ballContainer.begin());
 anotherDude->addBall(ball);
}

 

Så ønsker jeg nå å forandre på dette, så main kun starter funksjonen "dinTur" som jeg lager i r2d290, og at jeg en plass i r2d290-biblioteket starter funksjonen throwBall.

Problemet er bare at... fra r2d290 har jeg ikke noe som heter bruker2, ei heller Skybert.

 

Hvordan går jeg frem for å få kastet ballen fra r2d290 til Skybert?

Endret av r2d290 waits for Obi-Wan
Lenke til kommentar
Videoannonse
Annonse

Programmet skal simmulere personer som sitter i en ring og skal kaste ball til hverandre. I midten er det en "klokke" med sekundviser, og den personen som sekundviseren peker på, skal gjøre det han ønsker (enten kaste ballen, eller si noe morsomt).

 

Klokka (altså en løkke i main) sier altså hvem det er sin tur til å gjøre det de skal, også skal da hver person gjøre det de vil. Jeg ser det da som mer naturlig at personen velger hvem h*n skal kaste ballen til, enn at klokka forteller en person hvem han skal kaste ballen til.

 

Kan du ikke gi user2/skybert som argument til dinTur?

Hvordan gjøres dette?

 

Hva er problemet med hvordan det gjøres nå?

Indirekte besvart allerede. Altså at jeg finner det unaturlig at klokka (main) skal fortelle hvem en person skal kaste til.

 

Horribelt navn, dinTur, men.

Delvis enig. Bedre forslag tas imot med takk. Men det er jo på en måte det klokka sier mens den peker på en person. Derfor dette navnet.

Lenke til kommentar

Programmet skal simmulere personer som sitter i en ring og skal kaste ball til hverandre. I midten er det en "klokke" med sekundviser, og den personen som sekundviseren peker på, skal gjøre det han ønsker (enten kaste ballen, eller si noe morsomt).

Fair enough. Går det alltid på rundgang, altså sitter de en ring? Vil "neste" alltid være den samme, sett fra samme person?

 

Klokka (altså en løkke i main) sier altså hvem det er sin tur til å gjøre det de skal, også skal da hver person gjøre det de vil. Jeg ser det da som mer naturlig at personen velger hvem h*n skal kaste ballen til, enn at klokka forteller en person hvem han skal kaste ballen til.

I og for seg fint tenkt. Gitt at det er tilfeldig hvem som skal få neste: la alle objektene dine vite om alle (for eksempel ved å sende alle en vektor-peker og lagre den som en privat variabel) og så trekke tilfeldig fra denne vektoren, uten en selv, hver gang det er deres tur.

 

Hvordan gjøres dette?

Se over. Hjalp det, eller trenger du mer?

Indirekte besvart allerede. Altså at jeg finner det unaturlig at klokka (main) skal fortelle hvem en person skal kaste til.

Fint, sånne svar liker jeg. Bra tenkt.

Delvis enig. Bedre forslag tas imot med takk. Men det er jo på en måte det klokka sier mens den peker på en person. Derfor dette navnet.

Virker som om objektene dine bare skal ha én metode ut. Det er helt fint. Jeg vil enten brukt operator(), kalt den trigger (hvis det passer i kontekst av objektet ditt) eller receive() (her kan du også bruke catch_ball() eller tilsvarende)

 

Edit: huff, skrivefeil.

Endret av Lycantrophe
Lenke til kommentar
Fair enough. Går det alltid på rundgang, altså sitter de en ring? Vil "neste" alltid være den samme, sett fra samme person?

De sitter i en ring ja, og neste person vil alltid være den samme. Med det sagt, betyr ikke det at en person trenger å kaste ballen til "neste".

Men ja, rekkefølgen på dem er den samme hele tiden. De sitter i en ring fra bruker 1 til bruker x, og når bruker x er ferdig, går den videre til bruker 1 igjen.

 

I og for seg fint tenkt. Gitt at det er tilfeldig hvem som skal få neste:

Litt usikker på hva du mener med "Gitt at det er tilfeldig hvem som skal få neste". Poenget er i allefall at hver enkelt deltaker skal kunne velge hvem han skal kaste til. Det kan være at brukeren alltid vil kaste til Ola, eller det kan være en random person (alt avhengig av hvor avansert en person vil være).

 

la alle objektene dine vite om alle (for eksempel ved å sende alle en vektor-peker og lagre den som en privat variabel) og så trekke tilfeldig fra denne vektoren, uten en selv, hver gang det er deres tur.

Dette vil altså si at jeg fra main skal legge alle deltakerne inn i en vektor, og at alle deltakerne skal få tilgang til denne vektoren? Høres jo igrunn logisk ut.

 

Se over. Hjalp det, eller trenger du mer?

Må si jeg er litt usikker på detaljene. Litt uklart hvor den private variabelen skal være, hvor jeg skal opprette vektoren med brukere, og hvordan de ulike objektene skal få tilgang til disse.

 

"Trigger" kan være et aktuelt alternativt navn ja :)

 

Det jeg vil at funksjonen "Trigger" skal gjøre, er først å kalle en print-funksjon som skal skrive ut alle ballene som den aktuelle brukeren holder på.

Deretter aktivere "ThrowBall" som skal få brukeren til å kaste ball til en person.

Lenke til kommentar

De sitter i en ring ja, og neste person vil alltid være den samme. Med det sagt, betyr ikke det at en person trenger å kaste ballen til "neste".

Da vil ikke den til ens høyre alltid være neste. :) Hvordan de "fysisk sitter" er irrelevant hvis de ikke alltid kaster samme retning.

Litt usikker på hva du mener med "Gitt at det er tilfeldig hvem som skal få neste". Poenget er i allefall at hver enkelt deltaker skal kunne velge hvem han skal kaste til. Det kan være at brukeren alltid vil kaste til Ola, eller det kan være en random person (alt avhengig av hvor avansert en person vil være).

Hva er dette valget basert på? Brukerinput? Regler? Bare trekke en?

Dette vil altså si at jeg fra main skal legge alle deltakerne inn i en vektor, og at alle deltakerne skal få tilgang til denne vektoren? Høres jo igrunn logisk ut.

Yep. Om du lagrer objektene i vektoren eller bare pekere til de er ikke så viktig, så lenge det ikke er kopier og du får dobbeltlagring.

 

Må si jeg er litt usikker på detaljene. Litt uklart hvor den private variabelen skal være, hvor jeg skal opprette vektoren med brukere, og hvordan de ulike objektene skal få tilgang til disse.

Et eksempel:

class Person {
Person( std::vector< Person* >& others ) : others( &others ) {}
private:
std::vector< Person* >* others;
};

 

Det jeg vil at funksjonen "Trigger" skal gjøre, er først å kalle en print-funksjon som skal skrive ut alle ballene som den aktuelle brukeren holder på.

Deretter aktivere "ThrowBall" som skal få brukeren til å kaste ball til en person.

Det er bare å la den gjøre det.

 

Edit: Om noe er uklart må du selvfølgelig ikke nøle med å spørre.

Endret av Lycantrophe
Lenke til kommentar
Hva er dette valget basert på? Brukerinput? Regler? Bare trekke en?

Det er basert på hvordan/hvor avansert personen som lager dette klassebiblioteket (er det det det heter?) ønsker å lage den. Poenget som ligger bak, er altså at ulike personer skal lage hvert sitt slikt bibliotek, og alle skal fungere sammen.

Et eksempel kan f.eks. være at en av brukerne vil lage en fast regel for seg selv om at h*n alltid skal kaste ballen til den som sitter to plasser til venstre for den. En annen person kan ha en fast regel for seg selv om at han alltid skal kaste til personen som heter Ola, mens en tredje person alltid kaster ballen til en random person.

 

Altså skal ingen av disse bibliotekene være like.

 

Yep. Om du lagrer objektene i vektoren eller bare pekere til de er ikke så viktig, så lenge det ikke er kopier og du får dobbeltlagring.

Jeg forstår. Jeg skal se litt på det :)

 

 

Takk for hjelpen så langt! Jeg må fordøye det litt nå, så kommer jeg tilbake med hvordan det gikk :)

Lenke til kommentar

Det er basert på hvordan/hvor avansert personen som lager dette klassebiblioteket (er det det det heter?) ønsker å lage den. Poenget som ligger bak, er altså at ulike personer skal lage hvert sitt slikt bibliotek, og alle skal fungere sammen.

Aye, isåfall bør en public trigger være det du trenger, så kan de implementere hver sin throw().

 

Takk for hjelpen så langt! Jeg må fordøye det litt nå, så kommer jeg tilbake med hvordan det gikk :)

Den er god, lykke til. Endret av Lycantrophe
Lenke til kommentar

Jeg har kommet litt videre nå, samt tenkt litt mer på hvordan jeg ønsker strukturen.

 

Klassebibliotekene "r2d290" og "Skybert" arver addBall(den brukes for å tildele de 3 ballene til ulike brukere i starten av leken) og action (det nye navnet for "dinTur").

 

Jeg bruker virtual void på addBall og action, for da tvinger jeg alle de som skal lage nye klassebibliotek til å benytte nettopp disse funksjonene. (Hvis jeg har forstått det rett).

 

Som du nevner, har jeg laget en vector for å legge alle brukerne inn i disse, og så sende disse til alle brukerne.

Det har jeg vel på sett og vis fått til:

 

main.cpp:

int main()
{
People* R2d290;
People* skybert;
//Skybert* skybert;

std::vector<People*> peopleContainer;
peopleContainer.push_back(R2d290);
peopleContainer.push_back(skybert);

R2d290 = new r2d290("usr_r2d290", peopleContainer);
skybert = new Skybert("usr_skybert", peopleContainer);
[...]
}

 

Og med følgende kode i r2d290.cpp får jeg tallet 2 som utskrift. Altså tar r2d290 åpenbart imot vektoren med r2d290 og Skybert.

 

r2d290::r2d290(std::string name, std::vector<People*> container)
: People(name)
{
peopleContainer = container;
std::cout << container.size();
}

 

 

Så langt, så vel...

Nå er det to ting som gjenstår. Fra main ønsker jeg å kjøre en for-løkke som ber alle klassebibliotekene om å gjøre sitt. Den øverste linja (som er den jeg ønsker å få til) gir meg runtime-error: Segmentation fault (core dumped). Derimot fungerer den nederste linja (den som er kommentert bort) knirkefritt, og jeg får kjørt testutskriften 2 ganger, som jeg har laget i skybert.cpp:

for(int i = 0; i < peopleContainer.size(); i++)
		{
			peopleContainer[i]->action();
			//skybert->action();
		}

 

Det andre er å få til å kaste ballen mellom brukerne, men jeg tror jeg skal prøve å få til dette selv, bare jeg finner en løsning på denne segmention faulten

Endret av r2d290 waits for Obi-Wan
Lenke til kommentar

Jeg bruker virtual void på addBall og action, for da tvinger jeg alle de som skal lage nye klassebibliotek til å benytte nettopp disse funksjonene. (Hvis jeg har forstått det rett).

Hvis du vil tvinge de til å implementere de må du gjøre den pure virtual. Virtual gir de muligheten, pure virtual tvinger. Syntax:

 

virtual void override_me(); // virtual
virtual void override_me_or_gtfo() = 0; // pure virtual

 

 

main.cpp:

int main()
{
People* R2d290;
People* skybert;
//Skybert* skybert;

std::vector<People*> peopleContainer;
peopleContainer.push_back(R2d290);
peopleContainer.push_back(skybert);

R2d290 = new r2d290("usr_r2d290", peopleContainer);
skybert = new Skybert("usr_skybert", peopleContainer);
[...]
}

Litt forsiktig her. Legg merke til at du sender en kopi av hele vektoren. Du ønsker (antagelig) bare å sende en peker. Om du gjør det kan du legge til -flere- spillere etter at du har laget de og alle vil få vite hvem som har blitt med på leken. I tillegg blir det mer effektivt fordi du ikke kopierer så mye. Vet du hvordan du skal (om du faktisk velger det, da :----p) fikse det?

 

Så langt, så vel...

Nå er det to ting som gjenstår. Fra main ønsker jeg å kjøre en for-løkke som ber alle klassebibliotekene om å gjøre sitt. Den øverste linja (som er den jeg ønsker å få til) gir meg runtime-error: Segmentation fault (core dumped). Derimot fungerer den nederste linja (den som er kommentert bort) knirkefritt, og jeg får kjørt testutskriften 2 ganger, som jeg har laget i skybert.cpp:

for(int i = 0; i < peopleContainer.size(); i++)
		{
			peopleContainer[i]->action();
			//skybert->action();
		}

 

Det andre er å få til å kaste ballen mellom brukerne, men jeg tror jeg skal prøve å få til dette selv, bare jeg finner en løsning på denne segmention faulten

 

Ok, det du nå gjør er dette:

 

Du lager en peker til hver av deltakerene, men du gir de ingen verdi. Så dytter du pekerene (nå uten verdi) inn i vektoren. Deretter lager du deltakerene og setter pekerene til å peke til de. Disse ligger aldri i vektoren, der ligger det antagelig garbage.

 

Du må altså konstruere deltakerene først.

 

auto r2d2 = new R2D2();
auto Skybert = new Skybert();

vector< Person* > persons;
persons.push_back( r2d2 );
persons.push_back( Skybert );

for-loop{}

Endret av Lycantrophe
Lenke til kommentar

Det er pure virtual jeg har brukt, ser jeg. Har = 0 på slutten. Fikk litt hjelp med den biten der, så ikke alt jeg hang med på der og da.

 

Du ønsker (antagelig) bare å sende en peker. [...] Vet du hvordan du skal (om du faktisk velger det, da :----p) fikse det?

Jeg fant følgende:

vector<account> vec_account; //creates a vector of accounts
vector<account> * p; //creates a pointer to a vector of accounts
get_accounts(vec_account); //fills the vector with accounts
p=&vec_account; //stores the base address of the vector into the pointer

 

Jeg lager altså vektoren ved å skrive:

 

std::vector<People*> peopleContainer;

Så hvis jeg istede ønsker å sende pekere, må jeg bytte ut linja jeg har skrevet ovenfor, med:

std::vector<People*> * peopleContainer;

og da can push_back og sende-linja være lik som den var?

 

Og for å ta imot dette, skrev jeg tidligere (i f.eks. r2d290-klassen):

r2d290::r2d290(std::string name, std::vector<People*> container)
: People(name)

som må byttes ut med:

r2d290::r2d290(std::string name, std::vector<People*> * container)
: People(name)

 

Eller er jeg ute og kjører nå?

 

 

Ok, det du nå gjør er dette:

Du lager en peker til hver av deltakerene, men du gir de ingen verdi. Så dytter du pekerene (nå uten verdi) inn i vektoren. Deretter lager du deltakerene og setter pekerene til å peke til de. Disse ligger aldri i vektoren, der ligger det antagelig garbage.

Du må altså konstruere deltakerene først.

 

Grunnen til at jeg gjorde som jeg gjorde, var fordi:

Først prøvde jeg

r2d290* R2d290 = new r2d290("usr_r2d290", peopleContainer); //Denne lager objektet på heap
   Skybert* skybert = new Skybert("usr_skybert", peopleContainer);

   std::vector<People*> peopleContainer;
   peopleContainer.push_back(R2d290);
   peopleContainer.push_back(skybert);

 

Men da var ikke peopleContainer deklarert da jeg brukte den.

 

Byttet jeg plass på disse to bolkene, fikk jeg beskjed om at jeg bruker R2d290 uten å ha deklarert den. Derfor deklarerte jeg R2d290 (som du ser i tidligere post), uten å gi den noen verdi.

 

Det du sier jeg må gjøre, ser i prinsippet ganske likt ut som det jeg har sitert rett ovenfor, bare at du benytter "auto" istedefor "Skybert*", samt at du ikke har noen parametre i eksempelet ditt. Jeg har ikke helt klart å forstå hva slags magi "auto" utfører, men jeg forsto det sånn at Auto automatisk tilordner en verdi til en passende datatype så det skal bli lettere å skrive. Jeg forstår det altså sånn at jeg like gjerne kunne skrevet Skybert* istede for auto?

 

Det du altså gjør, for å slippe unna problemet jeg hadde med å sende peopleContainer uten at den var deklarert, er å la vær å sende den?

 

Dette lar seg kanskje gjøre fordi vi fra nå ønsker å sende vektorpekere istede for kopi av hele vektoren? Men hva hvis jeg likevel skulle ønsket å sende kopi av hele vektoren?

Lenke til kommentar

Det er pure virtual jeg har brukt, ser jeg. Har = 0 på slutten. Fikk litt hjelp med den biten der, så ikke alt jeg hang med på der og da.

Supert.

 

Jeg lager altså vektoren ved å skrive:

 

std::vector<People*> peopleContainer;

Så hvis jeg istede ønsker å sende pekere, må jeg bytte ut linja jeg har skrevet ovenfor, med:

std::vector<People*> * peopleContainer;

og da can push_back og sende-linja være lik som den var?

Nei, da må du bruke ->. Det er ikke noe problem å deklarere vektoren som du gjør nå, men du må sende inn pekere i stedet for kopier. Det gjøres med &-syntaxen.

 

Når jeg tenker meg om: Forslaget jeg skrev for Person GJØR dette for deg, men gjør det i constructoren. Hvordan ser din kode ut der? Om du kopierte mitt kan du se bort ifra dette. :>

Og for å ta imot dette, skrev jeg tidligere (i f.eks. r2d290-klassen):

r2d290::r2d290(std::string name, std::vector<People*> container)
: People(name)

som må byttes ut med:

r2d290::r2d290(std::string name, std::vector<People*> * container)
: People(name)

Stemmer.

 

Eller er jeg ute og kjører nå?

Nix.

 

 

Grunnen til at jeg gjorde som jeg gjorde, var fordi:

Først prøvde jeg

r2d290* R2d290 = new r2d290("usr_r2d290", peopleContainer); //Denne lager objektet på heap
Skybert* skybert = new Skybert("usr_skybert", peoplontainer);

std::vector<People*> peopleContainer;
peopleContainer.push_back(R2d290);
peopleContainer.push_back(skybert);

 

Men da var ikke peopleContainer deklarert da jeg brukte den.

Nei, den må isåfall deklareres og initialiseres først. Innholdet i den, derimot, kan fylles senere (hvis du bruker peker til vektoren).

Byttet jeg plass på disse to bolkene, fikk jeg beskjed om at jeg bruker R2d290 uten å ha deklarert den. Derfor deklarerte jeg R2d290 (som du ser i tidligere post), uten å gi den noen verdi.

 

Det du sier jeg må gjøre, ser i prinsippet ganske likt ut som det jeg har sitert rett ovenfor, bare at du benytter "auto" istedefor "Skybert*", samt at du ikke har noen parametre i eksempelet ditt. Jeg har ikke helt klart å forstå hva slags magi "auto" utfører, men jeg forsto det sånn at Auto automatisk tilordner en verdi til en passende datatype så det skal bli lettere å skrive. Jeg forstår det altså sånn at jeg like gjerne kunne skrevet Skybert* istede for auto?

Jeg benytter auto fordi det da er likegyldig hvilken type det er en C++11-feature, så du kan like gjerne bruke Skybert* i stedet.

 

Auto gjør akkurat det du tror, ja, den deduserer seg frem til hvilken type det skal være og enforcer denne deretter.

Det du altså gjør, for å slippe unna problemet jeg hadde med å sende peopleContainer uten at den var deklarert, er å la vær å sende den?

Ja, og heller sende en peker til den.

Dette lar seg kanskje gjøre fordi vi fra nå ønsker å sende vektorpekere istede for kopi av hele vektoren? Men hva hvis jeg likevel skulle ønsket å sende kopi av hele vektoren?

Så må du fjerne * etter vektoren, altså slik at du får:

std::vector< Person* > vect;

"Problemet" da er at du ikke helt uten videre kan legge til nye deltakere i ringen, og du vil også få en del kopieringsoverhead.

Lenke til kommentar

Jeg tror jeg begynner å nerme meg noe etterhvert.

 

Nå lager jeg peopleContainer i main, og sender minneadressen til denne, til både r2d290 og Sskybert:

std::vector< People* > peopleContainer;
   r2d290* R2d290 = new r2d290("usr_r2d290", &peopleContainer);
   Skybert* skybert = new Skybert("usr_skybert", &peopleContainer);

   peopleContainer.push_back(R2d290);
   peopleContainer.push_back(skybert);

 

Så printer jeg ut størrelsen på peopleContainer i main, og får 2 som svar:

std::cout << "Minneadressen er: " << peopleContainer.size() << endl;

 

Og til slutt kjører jeg for-løkka (som nå fungerer som den skal):

for(int i = 0; i < peopleContainer.size(); i++)
	    {
		    peopleContainer[i]->action();
	    }

 

 

r2d290.h ser slik ut:

 

 

#ifndef R2D290_H
#define R2D290_H
#include <string>
#include <vector>
#include "Ball.h"
#include "People.h"
class r2d290 : public People
{
   public:
    //r2d290(std::string name, std::vector<People*> container);
    r2d290(std::string name, std::vector<People*> * container);
    virtual void addBall( Ball* ball );
    virtual void action();
    void printIt();
   protected:
   private:
    //Lager en container av type 'vector' som kan inneholde baller
    std::vector<Ball*> ballContainer;
    std::vector<People*> peopleContainer;
    std::string navn;
};
#endif // R2D290_H

 

 

 

og utklipp fra r2d290.cpp ser slik ut:

r2d290::r2d290(std::string name, std::vector<People*> * container)
: People(name)
{
   peopleContainer = * container;
   navn = name;
}
void r2d290::action()
{
   std::cout << "r2d290. " << navn << " " << peopleContainer.size() << std::endl;
}

 

Denne printer ut: r2d290. usr_r2d290 0

 

Skulle ikke denne ha skrevet ut størrelsen på innholdet til minneadressen til peopleContainer? Altså 2.

Og når jeg har fått til dette: Hvordan får jeg til, fra r2d290, å skrive ut usr_skybert?

blir det noe sånt som cout << peopleContainer[1]->navn (eller name?);

 

?

Lenke til kommentar

og utklipp fra r2d290.cpp ser slik ut:

r2d290::r2d290(std::string name, std::vector<People*> * container)
: People(name)
{
peopleContainer = * container;
navn = name;
}
void r2d290::action()
{
std::cout << "r2d290. " << navn << " " << peopleContainer.size() << std::endl;
}

Her har du et problem. Inne i klassen din kopierer du vektoren, men det du ønsker er å bare ta vare på pekeren.

Denne:

r2d290::r2d290(std::string name, std::vector<People*> * container)
: People(name)
{
peopleContainer = * container;
navn = name;
}

bør være:

 

r2d290::r2d290(std::string name, std::vector<People*> * container)
: People(name)
{
peopleContainer =  container;
navn = name;
}

 

I headeren må du du da forandre type på peopleContainer til std::vector< People* > * (altså legge til *).

 

Skulle ikke denne ha skrevet ut størrelsen på innholdet til minneadressen til peopleContainer? Altså 2.

 

Jo, men du har kopiert den (tomme), ikke bare pekeren til den.

 

Og når jeg har fått til dette: Hvordan får jeg til, fra r2d290, å skrive ut usr_skybert?

blir det noe sånt som cout << peopleContainer[1]->navn (eller name?);

 

?

 

peopleContainer->at( 1 )->name

Endret av Lycantrophe
Lenke til kommentar

Jeg fjernet stjernen forand container, og la til en stjerne etter <People*> i header-fila. Dette kompilerte fint.

 

Jo, men du har kopiert den (tomme), ikke bare pekeren til den.

Ok, så da jeg skrev peopleContainer = *container, ble det laget en kopi av hele vektoren, og denne økte aldri i størrelse. Derfor ble size stående som 0 for alltid. Men når jeg fjerner den stjernen, tar jeg kopi av pekeren, slik at begge blir pekere som peker mot samme område på heap, nemlig vektoren med personer i seg?

 

Greit, så nå er både peopleContainer og container pekere, og det å ta size() av disse pekerne gir 0 siden det bare er en peker. Så prøvde jeg nå å ta cout;;peopleContainer->size (gudene vet hvordan jeg kom på å prøve det) men det ser ut til å fungere :) Den skrev ut 2. :)

 

Jammen fikk jeg til å printe ut skybert til slutt også.

Hva betyr "at (1)"? Har aldri sett dette før. Hvorfor kan jeg ikke skrive peopleContainer[1]->name istede?

 

Jeg hadde Name i protected i headerfila til People, og da fikk jeg feilmelding. Flyttet den derfor til public, og da fungerte det så jeg fikk ut usr_skybert. Men, hvorfor fungerte det ikke å ha den i protected? Jeg trodde alle klasser som arvet fra People skulle kunne se det som ligger i protected.

Lenke til kommentar

Jeg fjernet stjernen forand container, og la til en stjerne etter <People*> i header-fila. Dette kompilerte fint.

Høy fem!

 

Ok, så da jeg skrev peopleContainer = *container, ble det laget en kopi av hele vektoren, og denne økte aldri i størrelse. Derfor ble size stående som 0 for alltid. Men når jeg fjerner den stjernen, tar jeg kopi av pekeren, slik at begge blir pekere som peker mot samme område på heap, nemlig vektoren med personer i seg?

Stemmer, akkurat sånn.

 

Greit, så nå er både peopleContainer og container pekere, og det å ta size() av disse pekerne gir 0 siden det bare er en peker. Så prøvde jeg nå å ta cout;;peopleContainer->size (gudene vet hvordan jeg kom på å prøve det) men det ser ut til å fungere :) Den skrev ut 2. :)

Du kan ikke ta size av en peker.

 

I C++ er det veldig vanlig å jobbe med pekere til objekter (for eksempel den this-pointeren). Om du skal ha tak på en metode på "vanlig" måte (for eksempel om du skulle emulere C++ i C) hadde du måttet skrive:

(*obj).method()

C++ gir deg syntaktisk sukker for dette:

obj->method

 

Det følger altså pekeren og kaller metoden (tenk deg at -> peker). Derfor fungerte det ikke med dot (.), men med pil (->).

Jammen fikk jeg til å printe ut skybert til slutt også.

Hva betyr "at (1)"? Har aldri sett dette før. Hvorfor kan jeg ikke skrive peopleContainer[1]->name istede?

Siden man gjerne jobber med pekere til objekter i C++ vil ikke []-operatoren fungere uten videre (siden pekere ikke har den). Isåfall måtte du skrevet

(*vector)[i]

Som neppe er det du er ute etter. Derfor har vektorer at()-metoden som gjør akkurat det samme som []-operatoren. Forskjellen er at at() kan brukes med peker:

myvector->at( i )

 

 

Jeg hadde Name i protected i headerfila til People, og da fikk jeg feilmelding. Flyttet den derfor til public, og da fungerte det så jeg fikk ut usr_skybert. Men, hvorfor fungerte det ikke å ha den i protected? Jeg trodde alle klasser som arvet fra People skulle kunne se det som ligger i protected.

Nei. Det kan skrives svære bøker om forskjellene og best practices her, men protected eksponerer bare variabelen i metoder i de arvede klassene. Stort sett er protected en uting. Om du vil kunne hente navn rett ut, lag en såkalt getter. Se under for eksempel. Jeg synes getters (og setters) er en uting, men noen ganger er det riktig.

 

std::string name() const { return this->name; }

 

Kall med

std::string navn = skybert->name();

 

Merk her at dersom du gjør Name private og implementerer name() i Person vil disse også være tilgjengelige i Skybert og R2d290, uten at subklassene kan gjøre noe med Name. Det er antagelig dette du ser etter.

Lenke til kommentar

Nå ser jeg at vector klassen har implementert [] operatoren så du kunne i teorien ha skrevet

myvector->[i]

men det ser litt rart ut i mine øyne så gå for "at" funksjonen i stedet. Dog vær oppmerksom på at den (i motsetning til [] operatoren) sjekker at element "i" finnes og kaster en exception hvis ikke.

Lenke til kommentar
  • 3 uker senere...

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...