|
| member initialisering af nedarvede members~ Fra : Klaus Hebsgaard |
Dato : 12-01-06 16:00 |
|
Hej
Jeg opdagede lige noget mærkeligt idag - tror jeg nok.
I C++ er det ikke lovligt at gøre følgende:
class base
{
public:
base(){};
protected:
int myprotmember;
};
class inherited : public base
{
public:
inherited():base(), myprotmember(1){};
};
Det der er problemet er at compileren ikke vil kendes ved at myprotmember er
medlem af inherited.
Fint nok tænkte jeg så prefixer jeg den bare med base:: men det giver samme
fejl.
Der er sikkert en helt logisk forklaring på det, men hvad er forklaringen?
På forhånd tak.
Klaus Hebsgaard
| |
Mogens Hansen (12-01-2006)
| Kommentar Fra : Mogens Hansen |
Dato : 12-01-06 16:36 |
|
"Klaus Hebsgaard" <klaus-fjern-dette@no.spamhebsgaard.dk> wrote in message
news:43c66ee7$0$1845$edfadb0f@dread11.news.tele.dk...
[8<8<8<]
> Der er sikkert en helt logisk forklaring på det, men hvad er forklaringen?
Der er en væsentlig skelnen mellem initialisering og tildeling (assignment).
Når constructor eksekveringen når til "inherited"'s constructor er "base"
objektet fuldstændigt initialiseret. Det betyder at "myprotmember" er fuldt
initialiseret og derfor ikke kan initialiseres igen.
Det du skal skrive er
class base
{
// ...
protected: // optional - might be public
base(int myprotmember_init_value) :
myprotmember(myprotmember_init_value) {}
// ...
};
class derived : public base
{
public:
derived() :
base(1) {}
};
For fuldstændighedens skyld skal det bemærkes at virtuelle base klasser
altid bliver initialiseret fra den mest afledte klasse. (Hvis det ikke
umiddelbart ringer en klokke hos dig, så fortvivl ikke - det er noget man
sjældent bruger)
Venlig hilsen
Mogens Hansen
| |
Klaus Hebsgaard (12-01-2006)
| Kommentar Fra : Klaus Hebsgaard |
Dato : 12-01-06 21:38 |
|
"Mogens Hansen" <mogens_h@dk-online.dk> skrev i en meddelelse
news:43c67754$0$67258$157c6196@dreader2.cybercity.dk...
>
> "Klaus Hebsgaard" <klaus-fjern-dette@no.spamhebsgaard.dk> wrote in message
> news:43c66ee7$0$1845$edfadb0f@dread11.news.tele.dk...
>
> [8<8<8<]
>> Der er sikkert en helt logisk forklaring på det, men hvad er
>> forklaringen?
>
> Der er en væsentlig skelnen mellem initialisering og tildeling
> (assignment).
> Når constructor eksekveringen når til "inherited"'s constructor er "base"
> objektet fuldstændigt initialiseret. Det betyder at "myprotmember" er
> fuldt initialiseret og derfor ikke kan initialiseres igen.
OK, i dette tilfælde er der vist ikke den store forskel på initialisering og
tildeling, er der eksempler hvor det er tydeligt at der er en forskel på
tildeling og initialisering? Og hvorfor denne skelnen?
>
> Det du skal skrive er
>
> class base
> {
> // ...
> protected: // optional - might be public
> base(int myprotmember_init_value) :
> myprotmember(myprotmember_init_value) {}
> // ...
> };
>
> class derived : public base
> {
> public:
> derived() :
> base(1) {}
> };
OK, det giver jo meget god mening, når engang jeg får hittet rede på
forskellen på initialisering og tildeling...
>
> For fuldstændighedens skyld skal det bemærkes at virtuelle base klasser
> altid bliver initialiseret fra den mest afledte klasse. (Hvis det ikke
> umiddelbart ringer en klokke hos dig, så fortvivl ikke - det er noget man
> sjældent bruger)
>
OK.
> Venlig hilsen
>
> Mogens Hansen
>
Tak
| |
Mogens Hansen (12-01-2006)
| Kommentar Fra : Mogens Hansen |
Dato : 12-01-06 22:50 |
|
"Klaus Hebsgaard" <kh@sletdetteingenioer.dk> wrote in message
news:43c6be15$0$38650$edfadb0f@dread12.news.tele.dk...
[8<8<8<]
> OK, i dette tilfælde er der vist ikke den store forskel på initialisering
> og tildeling, er der eksempler hvor det er tydeligt at der er en forskel
> på tildeling og initialisering?
Et simpelt eksempel, hvis du ændrer din kode en lille smule:
class base
{
protected:
base(int i_init_value) :
i(i_init_value) {}
const int i;
};
Så er "i" konstant og kan ikke tildeles (med mindre man caster const væk).
Dens værdi skal derfor etableres når det oprettes.
For referencer gælder det altid at de skal initialiseres og aldrig senere
kan tildeles en ny værdi.
> Og hvorfor denne skelnen?
Initialisering er processen hvor man går fra ingenting (rå hukommelse) til
et gyldigt objekt. Den process varetages af constructoren.
Tildeling er processen hvor et objekt går fra een gyldig tilstand til en
anden gyldig tilstand. Den process varetages af assignment operatoren.
Det er langt fra alle typer hvor tildeling giver mening. Det gælder ofte for
klasser i et klasse hieraki.
Tildeling giver mening på typer der har værdi semantik som f.eks. "int",
"std::string", "std::complex" og dato typer. De kan frit (og ofte billigt)
tildeles og kopieres.
Typer med stærk identitet (f.eks. en bank konto objekt eller person objekt)
kan ikke frit kopieres og tildeles. Selv om de har samme værdi (ingen penge
på kontoen eller samme navn) er det væsentligt at skelne det ene objekt fra
det andet (din tomme konto og min tomme konto).
Men det giver for alle typer mening at initialisere dem.
Venlig hilsen
Mogens Hansen
| |
Klaus Hebsgaard (13-01-2006)
| Kommentar Fra : Klaus Hebsgaard |
Dato : 13-01-06 11:12 |
|
Tusind tak Mogens
Jeg blev godt nok en hel del klogere her
MVH
Klaus
| |
Thorsten Ottosen (12-01-2006)
| Kommentar Fra : Thorsten Ottosen |
Dato : 12-01-06 16:38 |
|
Klaus Hebsgaard wrote:
> Hej
>
> Jeg opdagede lige noget mærkeligt idag - tror jeg nok.
>
> I C++ er det ikke lovligt at gøre følgende:
>
> class base
>
> {
>
> public:
>
> base(){};
>
> protected:
>
> int myprotmember;
>
> };
>
> class inherited : public base
>
> {
>
> public:
>
> inherited():base(), myprotmember(1){};
>
> };
>
> Det der er problemet er at compileren ikke vil kendes ved at myprotmember er
> medlem af inherited.
> Fint nok tænkte jeg så prefixer jeg den bare med base:: men det giver samme
> fejl.
>
> Der er sikkert en helt logisk forklaring på det, men hvad er forklaringen?
Initialiser member variable i den classe, de defineres i. Du kan evt
initialisere variable i kroppen på konstruktoren.
-Thorsten
| |
Mogens Hansen (12-01-2006)
| Kommentar Fra : Mogens Hansen |
Dato : 12-01-06 17:09 |
|
Hej Thorsten,
"Thorsten Ottosen" <thorsten.ottosen@dezide.com> wrote in message
news:43c677d4$0$78285$157c6196@dreader1.cybercity.dk...
[8<8<8<]
> Du kan evt initialisere variable i kroppen på konstruktoren.
Jeg antager at du mener tildele i stedet for initialisere.
Venlig hilsen
Mogens Hansen
| |
Thorsten Ottosen (12-01-2006)
| Kommentar Fra : Thorsten Ottosen |
Dato : 12-01-06 17:36 |
|
Mogens Hansen wrote:
> Hej Thorsten,
>
>
> "Thorsten Ottosen" <thorsten.ottosen@dezide.com> wrote in message
> news:43c677d4$0$78285$157c6196@dreader1.cybercity.dk...
>
> [8<8<8<]
>
>>Du kan evt initialisere variable i kroppen på konstruktoren.
>
>
> Jeg antager at du mener tildele i stedet for initialisere.
yes, tak for rettelsen. Jeg vender mig aldrig til en dansk terminologi
-Thorsten
| |
|
|