25. juni 2009 - 12:48Der er
10 kommentarer og 1 løsning
const attributer og multipel nedarvning
Jeg mangler lidt forståelse for hvorfor min kode virker som den gør... Og så kan jeg ikke finde ud af at udvide min kode til det jeg egentligt skal bruge.
Jeg er ved at lave et program der kan håndtere en hel del forskellige slags måleinstrumenter. Derfor har jeg lavet et hiraki af generelle typer, og de er så vider specialiceret i konkrete typer af instrumenter.
Alle instrumenter skal indeholde deres navn, så det har jeg i den øverste klasse i mit hiraki.
class Instrument { public: const char Name[];
Instrument(const char Name[]) : Name(Name) {}; }
Denne klasse bliver så bla. nedarvet i en strømforsynings klasse, hvis konstruktor kalder sin forfaders konstruktor
class InstrumentPSU : virtual public Instrument { public: InstrumentPSU(const char Name[]) : Instrument(Name) {}; }
Jeg har så en specifik strøm forsynings type, som jeg opretter i en klasse. Men hvorfor skal den både kalde konstruktoren i Instrument og InstrumentPSU ?
class AgilentE3631A : virtual public InstrumentPSU { public: AgilentE3631A() : InstrumentPSU("HEWLET_PACKARD,E3631A"), Instrument("HEWLET_PACKARD,E3631A") {}; }
Jeg ville jo mene det var nok bare at kalde konstruktoren fra InstrumentPSU.
Hvis jeg lavet en default konstruktor i InstrumentPSU, og så nøjes med at kalde konstruktoren for Instrument i min specifikke klasse. Det hjælper da lidt på den fremtidige vedligeholdelse, men jeg undre mig bare...
Der ud over vil jeg gerne have at et instrument kan have flere navne (HP har skiftet navn til Agilent, og derfor kan samme instrument både hede HEWLET-PACKARD og AGILENT).
Det vil sige jeg vil gerne have 'Name' attributen til at være en 'const char *[]'. Hvordan for jeg initialiceret den fra min konstruktor? Noget i stil med: AgilentE3631A() : Instrument({"HEWLET_PACKARD", "AGILENT"})
Hvis jeg laver en Instrument() : names(NULL) { }; Kan min kode kompilere, men navnet af min Agilent bliver NULL, hvilket jo da kunne indikere at Instrument konstruktoren bliver kaldt til sidste, selv om jeg ville mene det skulle være den første der blev kaldt.
Det første kode jeg har sendt, virker efter hensigten. Jeg kan bare ikke lige regne ud hvorfor jeg ikke kan kalde konstruktoren fra den klasse jeg arver fra, men i stedet bliver nødt til at kalde konstruktoren fra den øverst base klasse.
Grunden til at alle arver virtuelt er, at nogle instrumenter indeholder flere funktionaliteter, og derfor skal arve fra flere generelle instrumenter.
Det kom jeg godt i tanke om her i nat en gang, altså at problemet er, at jeg atver virtuelt :)
Hvis ikke B2 konstruktoren blev kaldt fra DD2, ville det jo give mest mening at de 2 sidste Print() skulle skrive hhv 123 og 456. Men da de arver virtuelt, er der kun én v, og dermed vil den have værdien af den sidste der har skrevet til den, hvilket ville være 456.
Nu hvor B2 konstruktoren bliver kaldt, er det den der er den sidste der skriver til den, og derfor skriver de begge 789.
Men nu har jeg fået en ny ting at undre mig over. Hvorfor virker dit exempel med B1 og DD1? Jeg troede jo at når man laver multipel arv, uden at gøre det virtuelt, ville man få flere forekomster af de variabler der er erklæret i de øvre baser. Det vil så i dette tilfælde sige, at jeg var sikker på at exemplet ville give en compiler fejl i DD1, fordi v blev erklæret flere gange. Jeg er faktisk helt sikker på at jeg har set klasse exemplet (den med person; studerende:person; lære:person; tutor:studerende,lære ) på dette fejl.
1 virker fint. Ja - der er to forekomster af B1 hvilket ses tydeligt af at de to Print udskriver forskellige tal. Det er ikke et problem at der er en v i begge forekomster.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.