"Mark" <no@email.dk> wrote:
[8<8<8<]
> Er der nogle der kan kaste lidt lys over dette?!
Det er initializer listen.
Mellem ':' og '{' står hvordan basis-klasse og data-medlemmer bliver
initialiseret.
For begge dele gælder at hvis der ikke står noget vil default constructoren
blive brugt til at initialisere den pågældende del med.
Hvis en given del (hvad enten det er en basis-klasse eller et data-medlem)
ikke har nogen default constructor er man _nødt_ til at angive hvordan det
skal initialiseres - eller kan man bruge tildeling.
Dette gælder f.eks. for klasser uden default constructor, eller for noget så
simpelt som en reference:
(ikke compileret - der kan være småfejl)
class foo
{
public:
foo(int& i_arg) :
i(i_arg) // brug af initializer liste er påkrævet!!!
{}
private:
int& i;
};
I C++ er der en væsentlig skelnen mellem initialisering (oprettelse af et
ikke tidligere eksisterende objekt - constructor) og tildeling (tildeling
til et allerede eksisterende objekt - assignment operator).
Almindeligvis foretrækker man brug af initializer listen frem for
assignment.
Dels fremgår det tydeligt (når man ved det - men sådan er det altid) at der
er tale om initialisering, dels kan der være en performance fordel.
F.eks.
(ikke compileret - der kan være småfejl)
class foo
{
public:
foo(const char* s_arg);
private:
std::string s;
};
hvis man skriver
foo::foo(const char* s_arg) :
s(s_arg)
{
}
bliver string objektet "s" initialiseret med den nul-terminerede tekst
"s_arg".
hvis man skriver
foo::foo(const char* s_arg)
{
s = s_arg;
}
bliver string objektet "s" default konstrueres (som en tom streng),
hvorefter det tildeles en værdi svarende til den nul-terminerede tekst
"s_arg".
Når man er inde i constructorens funktions-krop er alle dele af foo objektet
initialiseret.
Det svarer nogenlunde til forskellen mellem at skrive
std::string s1("Hello world!");
og
std::string s2;
s2 = "Hello world!";
Bemærk iøvrigt at rækkefølgen som man skriver initializer-listen ikke er
afgørende for hvilken rækkefølge den eksekveres.
Det er klasse-erklæringen der bestemmer det. Uden jeg skal gå ind i alle
detaljerne, så bliver basis-klassernes constructorer først kørt, hvorefter
data-medlemmer initialiseres i den rækkefølge de er erklæret.
Altså
class foo
{
public:
foo(int i_arg);
};
class bar : public foo
{
public:
bar(int i_arg, const char* s1_arg, const std::string& s2_arg);
private:
std::string s1;
std::string s2;
};
bar::bar(int i_arg, const char* s1_arg, const std::string& s2_arg) :
s2(s2_arg), // køres sidst
s1(s1_arg), // køres i midten
foo(i_arg) // køres først
{
}
Det er naturligvis anbefalelsesværdigt at skrive initialiserlisten således
at den eksekveres i samme rækkefølge som den skrive.
Venlig hilsen
Mogens Hansen
|