Hvordan: Arv og pointer

Tags:    c++ php sikkerhed kryptering digital signatur

Hej

Jeg undrer mig over, hvordan det er muligt for en pointer til en baseklasse at pege på en af dennes arveklasser.
Er der nogen der kan forklare dette?



7 svar postet i denne tråd vises herunder
1 indlæg har modtaget i alt 1 karma
Sorter efter stemmer Sorter efter dato
Som sagt er en pointer bare en adresse. Den peger i praksis på en byte et sted i hukommelsen (ikke din normale hukommelse, men en virtuel hukommelse, som Windows har tildelt dit program), ikke andet. 4 bytes kan udgøre en float ligesom en long (som er det samme som en int på 32-bit cpu'er), og når du skriver float *f, så peger f på den første byte i floating point tallet.
De 4 bytes kan sagtens indeholde alt muligt andet, men det er stadig kun 4 bytes.
Derfor kan dette godt kompileres:
Fold kodeboks ind/udKode 


Fold kodeboks ind/udKode 


I det første eksempel konverterer jeg en float til long, hvilket bare runder ned / skal runde ned, ifølge den seneste C++ standard (ISO99 så vidt jeg husker). Jeg tror at det er en del af standarden, men er ikke helt sikker.
I det andet eksempel vil variablen i bare pege på 4 bytes, der officielt indeholder data i floating point format, som jo altså er et andet tal i heltals format. Men da 4 bytes er 4 bytes, så vil compileren tro at det officielt er et heltal, da vi fortæller den det ved at lave en type-casting (long *).

Håber du forstår hvor jeg vil hen med dette indlæg. Ellers må du da godt spørge igen ;)

1101110100010110000101000001

[Redigeret d. 10/02-05 16:18:36 af Nicolai Lyster Fersner]



En pointer er bare en adresse til et sted i hukommelse, altså et 32-bit nummer på 32-bit cpu'er.

Ved at forud-deklarere en klasse, kan du godt lave en pointer til den, da det jo bare er et nummer.
Derfor behøver din compiler på det tidspunkt ikke vide noget om, hvad klassen egentlig indeholder.
Hvis du derimod prøver at tilgå en klasses elementer fra en pointer før klassen er deklareret, så vil du få en fejl, da compileren jo altså stadig ikke ved hvad klassen indeholder.

Forud-deklaration:
Fold kodeboks ind/udKode 


1101110100010110000101000001

[Redigeret d. 10/02-05 15:41:28 af Nicolai Lyster Fersner]



Men det er jo heller ikke muligt at få en intpointer til at pege på en float.
Et baseklasse og en arveklasse fylder vel ikke det samme?



Med hensyn til klassers størrelse, så kan det hurtigt blive ret avanceret hvis du vil vide den totale størrelse (da funktioner og virtuelle tabeller også optager plads, men det er på et andet plan, da compileren ordner dette).
Men hvis du kun vil vide hvor meget plads variablerne i klassen optager, så kan det demonstreres ved en enkel klasse og en tom arveklasse som disse:
Fold kodeboks ind/udKode 

Størrelsen for Base er 1 byte (da en char = 1 byte).
Da String importerer Base's variabler og funktioner, så vil String fylde 2 byte, da klassen String reelt ser ud som vist nedenunder.
String2 vil derimod kun være 1 byte, da den jo kun indeholder Base's variabler og funktioner.
Fold kodeboks ind/udKode 

Du kan altid afprøve en klasses variablers størrelse med printf("%d", sizeof(Base)); eller hvilken som helst anden klasse.
sizeof tæller altså kun variablernes størrelse med.

1101110100010110000101000001

[Redigeret d. 10/02-05 16:38:31 af Nicolai Lyster Fersner]



Okay, men som du selv skriver så er string stører end Base.
Hvordan kan det så være muligt at sige:

Base *pBase;
string enString;
pBase=&enstring;


Men man kan fx ikke skrive:

string *pString;
Base enBase;
pString=&enBase;

Og man skriver jo heller ikke:

int *pInt;
float enFloat;
pInt=&enFloat;



Man kan godt sætte en int * til at pege på en float og omvendt, det kræver måske en cast.
Men man kan ikke tilgå en pointer der peger på det "forkerte".

For at svare på dit oprindelige spørgsmål:
Det er nok muligt for en base klasse at have en pointer til en nedarvet klasse, men det er sansynligvis ikke nogen god idé.
Man kan normalt løse problemet ved at lave en (pure) virtual funktion i base klassen som den afledte klasse implementerer.



Ups, jeg har vist lavet en fejl.
Jeg har hele tiden brugt (pure) virtual i min base-klasse, men havde glemt at man derfor ikke kan lave et objekt af klassen. Hehe. Håber ikke jeg var til for meget besvær...



t