Menu
Coddy logo textTech

Wielokrotne dziedziczenie

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

C++ umożliwia klasie jednoczesne dziedziczenie po wielu klasach bazowych. Nazywa się to dziedziczeniem wielokrotnym i pozwala łączyć funkcje z różnych hierarchii klas.

Aby dziedziczyć po wielu klasach, oddziel je przecinkami:

class Printer {
public:
    void print() {
        std::cout << "Printing document" << std::endl;
    }
};

class Scanner {
public:
    void scan() {
        std::cout << "Scanning document" << std::endl;
    }
};

class MultiFunctionDevice : public Printer, public Scanner {
public:
    void copy() {
        scan();
        print();
    }
};

Klasa MultiFunctionDevice ma teraz dostęp do metod zarówno klasy Printer, jak i klasy Scanner:

MultiFunctionDevice mfd;
mfd.print();  // Z klasy Printer
mfd.scan();   // Z klasy Scanner
mfd.copy();   // Własna metoda

Konstruktory są wywoływane w kolejności, w jakiej klasy bazowe są wymienione w deklaracji dziedziczenia (od lewej do prawej), a destruktory w odwrotnej kolejności. Możesz przekazać argumenty do każdego konstruktora klasy bazowej na liście inicjalizacyjnej:

class MultiFunctionDevice : public Printer, public Scanner {
public:
    MultiFunctionDevice() : Printer(), Scanner() {}
};

Potencjalny problem pojawia się, gdy obie klasy bazowe mają składową o tej samej nazwie. Powoduje to niejednoznaczność, dlatego musisz użyć operatora rozstrzygania zakresu, aby określić, o którą z nich chodzi:

class A { public: void show() {} };
class B { public: void show() {} };
class C : public A, public B {};

C obj;
obj.A::show();  // Wywołaj wersję A
obj.B::show();  // Wywołaj wersję B

Dziedziczenie wielokrotne jest potężne, ale może prowadzić do złożonych sytuacji, zwłaszcza gdy klasy bazowe mają wspólnego przodka. Przyjrzymy się temu wyzwaniu w następnej lekcji.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system urządzeń inteligentnego domu, który łączy możliwości wielu klas bazowych za pomocą wielokrotnego dziedziczenia. Utworzysz urządzenia, które mogą zarówno łączyć się z WiFi, jak i być sterowane głosowo, a następnie połączysz te funkcje w jednym inteligentnym głośniku.

Rozmieścisz kod w trzech plikach:

  • WiFiDevice.h: Zdefiniuj klasę WiFiDevice, która reprezentuje dowolne urządzenie mogące łączyć się z siecią:
    • Pole chronione std::string networkName
    • Konstruktor, który przyjmuje nazwę sieci i ją zapisuje
    • Publiczna metoda connect(), która wypisuje: Connecting to WiFi: <networkName>
    • Publiczna metoda status(), która wypisuje: WiFi Status: Connected
  • VoiceControl.h: Zdefiniuj klasę VoiceControl, która reprezentuje dowolne urządzenie z funkcjami sterowania głosowego:
    • Pole chronione std::string assistantName
    • Konstruktor, który przyjmuje nazwę asystenta i ją zapisuje
    • Publiczna metoda listen(), która wypisuje: <assistantName> is listening...
    • Publiczna metoda status(), która wypisuje: Voice Status: Active
  • main.cpp: Wczytaj trzy dane wejściowe (każdą w osobnym wierszu):
    1. Nazwę urządzenia (ciąg znaków)
    2. Nazwę sieci WiFi (ciąg znaków)
    3. Nazwę asystenta głosowego (ciąg znaków)

    Zdefiniuj klasę SmartSpeaker, która publicznie dziedziczy zarówno po WiFiDevice, jak i po VoiceControl:

    • Prywatne pole std::string deviceName
    • Konstruktor, który przyjmuje wszystkie trzy parametry, przekazuje nazwę sieci do WiFiDevice i nazwę asystenta do VoiceControl za pomocą listy inicjalizacyjnej oraz zapisuje nazwę urządzenia
    • Metoda powerOn(), która wypisuje: <deviceName> powering on..., a następnie wywołuje connect() i listen()
    • Metoda showAllStatus(), która wypisuje nazwę urządzenia, a następnie używa operatora zakresu, aby wywołać obie metody status() i rozwiązać niejednoznaczność

    Utwórz obiekt SmartSpeaker z użyciem wczytanych wartości. Wywołaj powerOn(), wypisz pusty wiersz, a następnie wywołaj showAllStatus().

Na przykład dla danych wejściowych Echo, HomeNetwork i Alexa:

Echo powering on...
Connecting to WiFi: HomeNetwork
Alexa is listening...

Echo Status:
WiFi Status: Connected
Voice Status: Active

Metoda showAllStatus() powinna wypisać nazwę urządzenia, po której w tym samym wierszu następuje " Status:", a następnie wywołać metodę status() każdej klasy bazowej za pomocą WiFiDevice::status() i VoiceControl::status(), aby uniknąć niejednoznaczności, ponieważ obie klasy bazowe mają metodę o tej samej nazwie.

Spróbuj swoich sił

#include <iostream>
#include <string>
#include "WiFiDevice.h"
#include "VoiceControl.h"

using namespace std;

// TODO: Zdefiniuj klasę SmartSpeaker, która dziedziczy publicznie zarówno po WiFiDevice, jak i VoiceControl
// - Prywatne pole: deviceName (string)
// - Konstruktor: przyjmuje deviceName, networkName, assistantName
//   Użyj listy inicjalizacyjnej, aby przekazać networkName do WiFiDevice, a assistantName do VoiceControl
// - Metoda powerOn(): wypisuje "<deviceName> powering on...", a następnie wywołuje connect() i listen()
// - Metoda showAllStatus(): wypisuje "<deviceName> Status:", a następnie wywołuje obie metody status()
//   z użyciem operatora zasięgu (WiFiDevice::status() i VoiceControl::status())

class SmartSpeaker {
    // TODO: Zaimplementuj tutaj klasę SmartSpeaker
};

int main() {
    string deviceName, networkName, assistantName;
    getline(cin, deviceName);
    getline(cin, networkName);
    getline(cin, assistantName);

    // TODO: Utwórz obiekt SmartSpeaker z wartościami wejściowymi
    // TODO: Wywołaj powerOn()
    // TODO: Wypisz pustą linię
    // TODO: Wywołaj showAllStatus()

    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