Wywoływanie konstruktora domyślnego klasy pierwotnej przez klasę potomną C++

Początkujący
2011-09-10 00:45
Początkujący
0

Witam,
Piszę dla siebie program w języku C++, aby poznać podstawy programowania obiektowego, nauczyć się C++ i przy okazji programować matematyczne aplikacje. Wybrałem macierze, ponieważ jest to okazja, aby wykorzystać podstawową wiedzę z algebry, przy okazji możliwość dziedziczenia (część funkcji dla podklasy kwadratowa nie będzie działać dla klasy ogólnej).

  1. Nie rozumiem dlaczego konstruktory klasy potomnej wywołują konstruktor domyślny klasy bazowej.

Czy jest to domyślne zachowanie C++ i trzeba je mieć na uwadze przy projektowaniu klas? A może to błąd w moim kodzie?

Napisałem prosty program by zasymulować problem:

#include<iostream>

using namespace std;

class macierz {
public:
  macierz();
};

class kwadratowa : public macierz {
};

macierz::macierz() {
  cout << "Wywolano konstruktor domyslny klasy pierwotnej!" << endl;
}

int main(void)
{
  kwadratowa a;
  return 0;
}

Konstuktor domyślny klasy pierwotnej został wywołany, wydaje mi się więc, że tak powinno być. Mam więc pytanie:

  1. Czy można sprawić, by klasa potomna nie wywoływała domyślnego konstruktora klasy pierwotnej?
  2. A może klasy powinny być projektowane zawsze w taki sposób, aby dostosować się do tego zachowania?

Pozdrawiam,

Pozostało 580 znaków

2011-09-10 01:05

Rejestracja: 9 lat temu

Ostatnio: 2 lata temu

0

Konstruktor klasy bazowej jest zawsze wywoływany(przed konstruktorem klasy potomnej). Ma to swoje konkretne uzasadnienie - przecież to co zostało odziedziczone też musi zostać skonstruowane i właśnie za to odpowiada wywołanie konstruktora klasy bazowej. Możesz co najwyżej wskazać, który konstruktor klasy bazowej zostanie wywołany. Robi się to z poziomu konstruktora klasy potomnej na jego liście inicjalizacyjnej.

Pamiętaj, że klasa ZAWSZE ma konstruktor(nawet jak go explicite nie zdefiniujesz).


edytowany 1x, ostatnio: byku_guzio, 2011-09-10 01:06

Pozostało 580 znaków

Początkujący
2011-09-10 02:05
Początkujący
0

Dzięki.

Pozostało 580 znaków

blee
2011-09-10 07:25
blee
0

dodam, że identycznie ma się sprawa z destruktorami podczas dziedziczenia, jednak aby mechanizm ten działał jak należy i zostały wywołane wszystkie destruktory odpowiednich klas to destruktor w klasie bazowej powinien być wirtualny.

Pozostało 580 znaków

2011-09-10 09:53

Rejestracja: 8 lat temu

Ostatnio: 9 godzin temu

0

Ad. 1. Nawet jeśli można by było to było by to bardzo niestosowne
Ad. 2. I tak i nie. Możesz albo pozostać przy samych konstruktorach i się dostosowywać, albo zastosować wzorzec "init" i zrobić tak jak chcesz:

#include<iostream>

using namespace std;

class macierz {
public:
  macierz();
  virtual void init();
};

class kwadratowa : public macierz {
public:
  virtual void init();
};

macierz::macierz() {
  // inicjalizacja zmiennych bez przetwarzania
}

void macierz::init() {
  cout << "Inicjalizacja macierzy - klasy pierwotnej!" << endl;
}

void kwadratowa::init() {
  macierz::init();
  cout << "Inicjalizacja macierzy kwadratowej" << endl;
}

int main(void)
{
  kwadratowa a;
  a.init();
  return 0;
}

Zalety tego wzorca:

  • możesz stosować wyjątki w procesie inicjalizacji klasy
  • możesz wykorzystywać funkcje wirtualne
  • masz wpływ na kolejność inicjalizacji

Wada:

  • wymagane dodatkowe wywołanie funkcji

Szacuje się, że w Polsce brakuje 50 tys. programistów

Pozostało 580 znaków

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0