Menu
Coddy logo textTech

Konstruktory delegujące

Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 23 z 104.

Gdy masz wiele konstruktorów współdzielących wspólną logikę inicjalizacji, możesz użyć konstruktorów delegujących, aby uniknąć powielania kodu. Konstruktor delegujący wywołuje inny konstruktor tej samej klasy na swojej liście inicjalizacyjnej.

class Player {
    std::string name;
    int health;
    int level;
public:
    // Konstruktor główny – wykonuje właściwą pracę
    Player(std::string n, int h, int lvl) 
        : name(n), health(h), level(lvl) {}
    
    // Deleguje do konstruktora głównego
    Player(std::string n) : Player(n, 100, 1) {}
    
    // Konstruktor domyślny również deleguje
    Player() : Player("Unknown") {}
};

Delegowanie odbywa się na liście inicjalizacyjnej za pomocą nazwy klasy, po której następują argumenty. Gdy wywoływane jest Player(), deleguje ono do Player(std::string), które następnie deleguje do konstruktora z trzema parametrami. Łańcuch wykonuje się od konstruktora docelowego z powrotem do pierwotnego.

Jest jedna ważna zasada: konstruktor delegujący nie może mieć innych elementów na liście inicjalizacyjnej. Delegowanie musi być jedynym elementem:

class Item {
    int id;
    int value;
public:
    Item(int i, int v) : id(i), value(v) {}
    
    // Błąd! Nie można łączyć delegowania z inicjalizacją pól klasy
    // Item(int i) : Item(i, 0), id(i) {}
    
    // Poprawnie – tylko delegowanie
    Item(int i) : Item(i, 0) {}
};

Konstruktory delegujące pomagają scentralizować logikę inicjalizacji w jednym miejscu, dzięki czemu kod jest łatwiejszy w utrzymaniu i mniej podatny na błędy wynikające z powielania kodu.

challenge icon

Wyzwanie

Łatwy

Utwórzmy system ustawień połączenia, który pokazuje, jak konstruktory delegujące mogą wyeliminować powielanie kodu przez łańcuchowe wywoływanie konstruktorów.

Utworzysz dwa pliki, aby uporządkować kod:

  • Connection.h: Zdefiniuj klasę Connection, która reprezentuje połączenie sieciowe z różnymi opcjami konfiguracji. Twoja klasa powinna zawierać:
    • Prywatne składowe: host (string), port (int), timeout (int w sekundach) i secure (bool)
    • Konstruktor główny, który przyjmuje wszystkie cztery parametry i inicjalizuje wszystkie składowe za pomocą listy inicjalizacyjnej. Ten konstruktor powinien wypisać "Connection configured: <host>:<port>"
    • Konstruktor przyjmujący tylko host i port, który deleguje do konstruktora głównego, domyślnie ustawiając timeout na 30 i secure na false
    • Konstruktor przyjmujący tylko host, który deleguje do konstruktora dwuparametrowego, domyślnie ustawiając port na 80
    • Konstruktor domyślny, który deleguje do konstruktora jednoargumentowego, domyślnie ustawiając host na "localhost"
    • Metodę getInfo(), która zwraca ciąg znaków w formacie: "<host>:<port> (timeout: <timeout>s, secure: <yes/no>)"
  • main.cpp: Zademonstruj łańcuch delegowania, tworząc połączenia za pomocą różnych konstruktorów. Wczytaj nazwę hosta i numer portu z wejścia (każdy w osobnym wierszu), a następnie:
    • Utwórz obiekt Connection za pomocą konstruktora domyślnego
    • Utwórz obiekt Connection, używając tylko hosta z wejścia
    • Utwórz obiekt Connection, używając hosta i portu z wejścia
    • Utwórz obiekt Connection z hostem i portem z wejścia, wartością timeout równą 60 i ustawionym na true parametrem secure
    • Wypisz wynik getInfo() dla każdego połączenia, po jednym wierszu

Łańcuch delegowania przebiega następująco: konstruktor domyślny wywołuje konstruktor jednoargumentowy, który wywołuje konstruktor dwuargumentowy, a ten wywołuje główny konstruktor czteroargumentowy. Oznacza to, że komunikat "Connection configured" jest wypisywany raz dla każdego utworzonego obiektu, zawsze z konstruktora głównego.

W przypadku stanu zabezpieczenia w getInfo() wypisz "yes", jeśli secure ma wartość true, a w przeciwnym razie "no".

Dołącz plik nagłówkowy w main.cpp za pomocą #include "Connection.h".

Spróbuj swoich sił

#include <iostream>
#include <string>
#include "Connection.h"

using namespace std;

int main() {
    // Odczytaj dane wejściowe
    string host;
    int port;
    cin >> host;
    cin >> port;

    // TODO: Utwórz obiekt Connection za pomocą konstruktora domyślnego

    // TODO: Utwórz obiekt Connection, używając tylko host z danych wejściowych

    // TODO: Utwórz obiekt Connection, używając host i port z danych wejściowych

    // TODO: Utwórz obiekt Connection z host i port z danych wejściowych oraz timeout=60 i secure=true

    // TODO: Wypisz wynik getInfo() dla każdego połączenia, po jednym wierszu

    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C++ online