Menu
Coddy logo textTech

Ereditarietà multipla

Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 53 di 104.

C++ consente a una classe di ereditare da più classi base contemporaneamente. Questa pratica è chiamata ereditarietà multipla e ti permette di combinare funzionalità di gerarchie di classi diverse.

Per ereditare da più classi, separale con virgole:

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();
    }
};

La classe MultiFunctionDevice ora ha accesso ai metodi sia di Printer che di Scanner:

MultiFunctionDevice mfd;
mfd.print();  // Da Printer
mfd.scan();   // Da Scanner
mfd.copy();   // Il suo metodo

I costruttori vengono chiamati nell’ordine in cui le classi base sono elencate nella dichiarazione di ereditarietà (da sinistra a destra), mentre i distruttori vengono chiamati in ordine inverso. Puoi passare argomenti a ciascun costruttore base nell’elenco di inizializzazione:

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

Un potenziale problema si presenta quando entrambe le classi base hanno un membro con lo stesso nome. Questo crea ambiguità e devi usare l'operatore di risoluzione dell'ambito per specificare quale intendi:

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

C obj;
obj.A::show();  // Chiama la versione di A
obj.B::show();  // Chiama la versione di B

L'ereditarietà multipla è potente, ma può portare a situazioni complesse, soprattutto quando le classi base condividono un antenato comune. Esploreremo questa sfida nella prossima lezione.

challenge icon

Sfida

Facile

Costruiamo un sistema di dispositivi per la casa intelligente che combina le funzionalità di più classi base usando l'ereditarietà multipla. Creerai dispositivi che possono connettersi al WiFi ed essere controllati tramite la voce, per poi combinare queste funzionalità in uno smart speaker unificato.

Organizzerai il codice in tre file:

  • WiFiDevice.h: definisci una classe WiFiDevice che rappresenta qualsiasi dispositivo in grado di connettersi a una rete:
    • Un membro protetto std::string networkName
    • Un costruttore che accetta il nome di una rete e lo memorizza
    • Un metodo pubblico connect() che stampa: Connecting to WiFi: <networkName>
    • Un metodo pubblico status() che stampa: WiFi Status: Connected
  • VoiceControl.h: definisci una classe VoiceControl che rappresenta qualsiasi dispositivo con funzionalità vocali:
    • Un membro protetto std::string assistantName
    • Un costruttore che accetta il nome di un assistente e lo memorizza
    • Un metodo pubblico listen() che stampa: <assistantName> is listening...
    • Un metodo pubblico status() che stampa: Voice Status: Active
  • main.cpp: leggi tre input (ciascuno su una riga separata):
    1. Nome del dispositivo (stringa)
    2. Nome della rete WiFi (stringa)
    3. Nome dell'assistente vocale (stringa)

    Definisci una classe SmartSpeaker che eredita pubblicamente sia da WiFiDevice sia da VoiceControl:

    • Un membro privato std::string deviceName
    • Un costruttore che accetta tutti e tre i parametri, passa il nome della rete a WiFiDevice e il nome dell'assistente a VoiceControl usando la lista di inizializzazione e memorizza il nome del dispositivo
    • Un metodo powerOn() che stampa: <deviceName> powering on..., quindi chiama connect() e listen()
    • Un metodo showAllStatus() che stampa il nome del dispositivo, quindi usa l'operatore di risoluzione dell'ambito per chiamare entrambi i metodi status() e risolvere l'ambiguità

    Crea un oggetto SmartSpeaker con i valori di input. Chiama powerOn(), stampa una riga vuota, quindi chiama showAllStatus().

Ad esempio, con gli input Echo, HomeNetwork e Alexa:

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

Echo Status:
WiFi Status: Connected
Voice Status: Active

Il metodo showAllStatus() dovrebbe stampare il nome del dispositivo seguito da " Status:" su una riga, quindi chiamare il metodo status() di ciascuna classe base usando WiFiDevice::status() e VoiceControl::status() per evitare ambiguità, dato che entrambe le classi base hanno un metodo con lo stesso nome.

Provalo tu

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

using namespace std;

// TODO: Definire la classe SmartSpeaker che eredita pubblicamente sia da WiFiDevice sia da VoiceControl
// - Membro privato: deviceName (string)
// - Costruttore: accetta deviceName, networkName, assistantName
//   Usare la lista di inizializzazione per passare networkName a WiFiDevice e assistantName a VoiceControl
// - Metodo powerOn(): stampa "<deviceName> powering on...", poi chiama connect() e listen()
// - Metodo showAllStatus(): stampa "<deviceName> Status:", poi chiama entrambi i metodi status()
//   usando la risoluzione dell'ambito (WiFiDevice::status() e VoiceControl::status())

class SmartSpeaker {
    // TODO: Implementare qui la classe SmartSpeaker
};

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

    // TODO: Creare un oggetto SmartSpeaker con i valori di input
    // TODO: Chiamare powerOn()
    // TODO: Stampare una riga vuota
    // TODO: Chiamare showAllStatus()

    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C++ online