Jakie są zasady wywoływania konstruktora superclass?

Jakie są zasady C++ do wywoływania konstruktora superklasy z podklasy?

Na przykład, Wiem, że w Javie musisz to zrobić jako pierwsza linia konstruktora podklasy(a jeśli tego nie zrobisz, zakłada się niejawne wywołanie super konstruktora no-arg-co daje błąd kompilacji, jeśli tego nie ma).

Author: Melebius, 2008-09-23

9 answers

Konstruktory klas bazowych są automatycznie wywoływane, jeśli nie mają żadnego argumentu. Jeśli chcesz wywołać konstruktor klasy nadrzędnej z argumentem, musisz użyć listy inicjalizacji konstruktora klasy podrzędnej. W przeciwieństwie do Javy, C++ obsługuje dziedziczenie wielokrotne (na dobre i złe), więc klasa bazowa musi być określana nazwą, a nie " super ()".

class SuperClass
{
    public:

        SuperClass(int foo)
        {
            // do something with foo
        }
};

class SubClass : public SuperClass
{
    public:

        SubClass(int foo, int bar)
        : SuperClass(foo)    // Call the superclass constructor in the subclass' initialization list.
        {
            // do something with bar
        }
};

Więcej informacji o liście inicjalizacji konstruktora tutaj i tutaj .

 773
Author: luke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-08 18:44:25

W C++, konstruktory bez argumentu dla wszystkich superklas i zmiennych członkowskich są wywoływane dla Ciebie, przed wejściem do konstruktora. Jeśli chcesz przekazać im argumenty, istnieje osobna składnia o nazwie "łańcuchowanie konstruktora", która wygląda tak:

class Sub : public Base
{
  Sub(int x, int y)
  : Base(x), member(y)
  {
  }
  Type member;
};

Jeśli cokolwiek zostanie uruchomione w tym momencie, bazy/elementy, które wcześniej ukończyły budowę, mają wywoływane destruktory i wyjątek jest zwracany do wywołującego. Jeśli chcesz wyłapać wyjątki podczas łączenia należy użyć funkcji try block:

class Sub : public Base
{
  Sub(int x, int y)
  try : Base(x), member(y)
  {
    // function body goes here
  } catch(const ExceptionType &e) {
    throw kaboom();
  }
  Type member;
};

W tej formie zauważ, że blok try jest ciałem funkcji, a nie znajduje się wewnątrz ciała funkcji; pozwala to na przechwytywanie WYJĄTKÓW rzucanych przez niejawne lub jawne inicjalizacje klas członkowskich i bazowych, a także podczas ciała funkcji. Jednakże, jeśli blok funkcji nie wyrzuci innego wyjątku, runtime zmieni oryginalny błąd; wyjątki podczas inicjalizacji nie można ignorować.

 198
Author: puetzk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-01 18:50:52

W C++ istnieje koncepcja listy inicjalizacyjnej konstruktora, gdzie można i powinno się wywołać konstruktor klasy bazowej i gdzie należy również zainicjować elementy składowe danych. Lista inicjalizacyjna pojawia się po podpisie konstruktora za dwukropkiem, a przed ciałem konstruktora. Powiedzmy, że mamy klasę A:


class A : public B
{
public:
  A(int a, int b, int c);
private:
  int b_, c_;
};

Wtedy, zakładając, że B ma konstruktor, który przyjmuje int, konstruktor A może wyglądać tak:


A::A(int a, int b, int c) 
  : B(a), b_(b), c_(c) // initialization list
{
  // do something
}

Jak widać, konstruktor klasy bazowej jest wywoływany na liście inicjalizacyjnej. Nawiasem mówiąc, inicjalizacja składowych danych na liście inicjalizacyjnej jest korzystniejsza niż przypisywanie wartości dla b_ i c_ wewnątrz konstruktora, ponieważ oszczędzasz dodatkowy koszt przypisania.

Należy pamiętać, że członkowie danych są zawsze inicjalizowane w kolejności, w jakiej są zadeklarowane w definicji klasy, niezależnie od ich kolejności na liście inicjalizacyjnej. Aby uniknąć dziwnych błędów, które może się zdarzyć, jeśli członkowie danych zależą od siebie nawzajem, należy zawsze upewnić się, że kolejność członków jest taka sama na liście inicjalizacji i definicji klasy. Z tego samego powodu konstruktor klasy bazowej musi być pierwszą pozycją na liście inicjalizacyjnej. Jeśli całkowicie to pominiesz, wtedy domyślny konstruktor dla klasy bazowej zostanie wywołany automatycznie. W takim przypadku, jeśli klasa bazowa nie ma domyślnego konstruktora, pojawi się błąd kompilatora.

 44
Author: Dima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 13:34:21

Jedynym sposobem przekazywania wartości do konstruktora nadrzędnego jest lista inicjalizacyjna. Lista inicjalizacji jest zaimplementowana za pomocą znaku:, a następnie listy klas i wartości, które mają być przekazane do konstruktora klas.

Class2::Class2(string id) : Class1(id) {
....
}

Pamiętaj również, że jeśli masz konstruktor, który nie pobiera żadnych parametrów z klasy nadrzędnej, zostanie on wywołany automatycznie przed wykonaniem konstruktora potomnego.

 16
Author: CR.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 13:21:28

Jeśli masz konstruktor bez argumentów, zostanie on wywołany przed wykonaniem pochodnego konstruktora klasy.

Jeśli chcesz wywołać konstruktor bazowy z argumentami, musisz jawnie napisać, że w pochodnym konstruktorze jest tak:

class base
{
  public:
  base (int arg)
  {
  }
};

class derived : public base
{
  public:
  derived () : base (number)
  {
  }
};

Nie można skonstruować klasy pochodnej bez wywołania konstruktora parents w C++. To albo dzieje się automatycznie, jeśli jest nie-arg C ' Tor, dzieje się, jeśli wywołasz Pochodny konstruktor bezpośrednio, jak pokazano powyżej lub Twój kod nie będzie kompilowany.

 16
Author: Nils Pipenbrinck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-26 09:14:32

Wszyscy wspominali o wywołaniu konstruktora poprzez listę inicjalizacyjną, ale nikt nie powiedział, że konstruktor klasy nadrzędnej może być wywołany jawnie z pochodnego ciała konstruktora członka. Zobacz na przykład Pytanie wywołanie konstruktora klasy bazowej z ciała konstruktora klasy podklasy. Chodzi o to, że jeśli użyjesz jawnego wywołania do klasy nadrzędnej lub konstruktora super klasy w ciele klasy pochodnej, to w rzeczywistości jest to tylko tworzenie instancji rodzica klasy i nie wywołuje konstruktora klasy nadrzędnej na obiekcie pochodnym. Jedynym sposobem wywołania klasy nadrzędnej lub konstruktora klasy nadrzędnej na obiekcie klasy pochodnej jest lista inicjalizacyjna, a nie jej ciało konstruktora klasy pochodnej. Może więc nie powinno się go nazywać "superklasowym wywołaniem konstruktora". Tę odpowiedź umieściłem tutaj, ponieważ ktoś może się pomylić(tak jak ja).

 13
Author: TT_,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:38

Jeśli masz domyślne parametry w konstruktorze bazowym, klasa bazowa zostanie wywołana automatycznie.

using namespace std;

class Base
{
    public:
    Base(int a=1) : _a(a) {}

    protected:
    int _a;
};

class Derived : public Base
{
  public:
  Derived() {}

  void printit() { cout << _a << endl; }
};

int main()
{
   Derived d;
   d.printit();
   return 0;
}

Wyjście To: 1

 8
Author: edW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-15 18:49:38
CDerived::CDerived()
: CBase(...), iCount(0)  //this is the initialisation list. You can initialise member variables here too. (e.g. iCount := 0)
    {
    //construct body
    }
 6
Author: Dynite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 13:24:19

Nikt nie wspomniał o sekwencji wywołań konstruktora, gdy Klasa wywodzi się z wielu klas. Sekwencja jest jak wspomniano podczas wyprowadzania klas.

 2
Author: darth_coder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-20 02:26:40