16 lutego 2013

C++ COTW (Coś Of The Week)


class A
{
public:
       A(const char *sz)
       {
             printf("%s ", sz);
       }

       ~A()
       {
             printf("~A ");
       }
};

class B
{
public:
       B(const char *sz)
       {
             printf("%s ", sz);
       }

       ~B()
       {
             printf("~B ");
       }
};

class C
{
public:
       C(const char *sz)
       {
             printf("%s ", sz);
       }

       ~C()
       {
             printf("~C ");
       }
}; 

class App
{
public:
       App() : a("A"), b("B"), c("C") {printf("App");}

private:
       C c;
       B b;
       A a;
};

int main()
{
       {
             App m;
             printf("\n");
       }
       printf("\n");
}

Ktoś wie co pojawi się na wyjściu? Wbrew pozorom poprawną odpowiedzią będzie:
C B A App
~A ~B ~C
Nie wierzycie? Sprawdźcie sami. Co zatem z tego wynika? Elementy na liście inicjalizacyjnej konstruktora inicjowane są przed wywołaniem samego konstruktora (co jest dość oczywiste). Dodatkowo kolejność inicjalizacji jest zgodna z kolejnością deklaracji pól w klasie.  Destrukcja zaś odbywa się od ostatniego pola. 

2 komentarze:

  1. Generalnie żeby nie robić zamieszania należy inicjować elementy na liście w kolejności ich występowania w deklaracji klasy. AFAIR gcc pluje w warningach o tym, że kolejność jest zła.

    OdpowiedzUsuń
  2. Myślę, że warto by dodać, że nie jest to zachowanie zależne od kompilatora, tylko wymagane przez standard.
    12.6.2.10:
    Then, non-static data members are initialized in the order they were declared in the class definition
    (again regardless of the order of the mem-initializers).

    I przy okazji, imho łatwiej zapamiętać, że destrukcja obiektów ma tylko jedną zasadę: odwrotnie do kierunku inicjalizacji.

    OdpowiedzUsuń