Herança múltipla
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 53 de 104.
C++ permite que uma classe herde de várias classes-base simultaneamente. Isso é chamado de herança múltipla e permite combinar recursos de diferentes hierarquias de classes.
Para herdar de várias classes, separe-as com vírgulas:
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();
}
};A classe MultiFunctionDevice agora tem acesso a métodos de Printer e Scanner:
MultiFunctionDevice mfd;
mfd.print(); // Da classe Printer
mfd.scan(); // Da classe Scanner
mfd.copy(); // Seu próprio métodoOs construtores são chamados na ordem em que as classes-base são listadas na declaração de herança (da esquerda para a direita), e os destrutores, na ordem inversa. Você pode passar argumentos para cada construtor-base na lista de inicialização:
class MultiFunctionDevice : public Printer, public Scanner {
public:
MultiFunctionDevice() : Printer(), Scanner() {}
};Um possível problema surge quando ambas as classes base têm um membro com o mesmo nome. Isso cria ambiguidade, e você precisa usar o operador de resolução de escopo para especificar a qual deles se refere:
class A { public: void show() {} };
class B { public: void show() {} };
class C : public A, public B {};
C obj;
obj.A::show(); // Chama a versão de A
obj.B::show(); // Chama a versão de BA herança múltipla é poderosa, mas pode levar a situações complexas, especialmente quando as classes base compartilham um ancestral em comum. Vamos explorar esse desafio na próxima lição.
Desafio
FácilVamos criar um sistema de dispositivos para casa inteligente que combina recursos de várias classes-base usando herança múltipla. Você criará dispositivos que podem se conectar ao WiFi e ser controlados por voz e, em seguida, combinará esses recursos em uma única caixa de som inteligente.
Você organizará seu código em três arquivos:
WiFiDevice.h: Defina uma classeWiFiDeviceque representa qualquer dispositivo capaz de se conectar a uma rede:- Um membro protegido
std::string networkName - Um construtor que recebe um nome de rede e o armazena
- Um método público
connect()que imprime:Connecting to WiFi: <networkName> - Um método público
status()que imprime:WiFi Status: Connected
- Um membro protegido
VoiceControl.h: Defina uma classeVoiceControlque representa qualquer dispositivo com recursos de controle por voz:- Um membro protegido
std::string assistantName - Um construtor que recebe o nome de um assistente e o armazena
- Um método público
listen()que imprime:<assistantName> is listening... - Um método público
status()que imprime:Voice Status: Active
- Um membro protegido
main.cpp: Leia três entradas (cada uma em uma linha separada):- Nome do dispositivo (string)
- Nome da rede WiFi (string)
- Nome do assistente de voz (string)
Defina uma classe
SmartSpeakerque herda publicamente tanto deWiFiDevicequanto deVoiceControl:- Um membro privado
std::string deviceName - Um construtor que recebe os três parâmetros, passa o nome da rede para
WiFiDevicee o nome do assistente paraVoiceControlusando a lista de inicialização e armazena o nome do dispositivo - Um método
powerOn()que imprime:<deviceName> powering on...e, em seguida, chamaconnect()elisten() - Um método
showAllStatus()que imprime o nome do dispositivo e, em seguida, usa o operador de resolução de escopo para chamar os dois métodosstatus()e resolver a ambiguidade
Crie um objeto
SmartSpeakercom os valores de entrada. ChamepowerOn(), imprima uma linha em branco e, em seguida, chameshowAllStatus().
Por exemplo, com as entradas Echo, HomeNetwork e Alexa:
Echo powering on...
Connecting to WiFi: HomeNetwork
Alexa is listening...
Echo Status:
WiFi Status: Connected
Voice Status: ActiveO método showAllStatus() deve imprimir o nome do dispositivo seguido de " Status:" em uma linha e, em seguida, chamar o método status() de cada classe-base usando WiFiDevice::status() e VoiceControl::status() para evitar ambiguidade, já que ambas as classes-base têm um método com o mesmo nome.
Experimente você mesmo
#include <iostream>
#include <string>
#include "WiFiDevice.h"
#include "VoiceControl.h"
using namespace std;
// TODO: Defina a classe SmartSpeaker que herda publicamente de WiFiDevice e VoiceControl
// - Membro privado: deviceName (string)
// - Construtor: recebe deviceName, networkName, assistantName
// Use a lista de inicialização para passar networkName para WiFiDevice e assistantName para VoiceControl
// - Método powerOn(): imprime "<deviceName> powering on..." e, em seguida, chama connect() e listen()
// - Método showAllStatus(): imprime "<deviceName> Status:" e, em seguida, chama os dois métodos status()
// usando a resolução de escopo (WiFiDevice::status() e VoiceControl::status())
class SmartSpeaker {
// TODO: Implemente a classe SmartSpeaker aqui
};
int main() {
string deviceName, networkName, assistantName;
getline(cin, deviceName);
getline(cin, networkName);
getline(cin, assistantName);
// TODO: Crie um objeto SmartSpeaker com os valores de entrada
// TODO: Chame powerOn()
// TODO: Imprima uma linha em branco
// TODO: Chame showAllStatus()
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos externosBuild e compilação em C++Arquivos de cabeçalho e arquivos-fonteNamespaces e escopoIntrodução à POO em C++Classes vs. objetosO ponteiro 'this'Métodos (funções membro)Atributos (membros de dados)Noções básicas de construtores e destruidoresRevisão - calculadora simples4Propriedades de Classe
Membros de Instância vs. EstáticosGetters e SettersFunções Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRevisão - Gerenciador de Contas Bancárias7Herança
Herança básicaNíveis de acesso da herançaOrdem de chamada de construtor e destrutorSobrescrita de métodosFunções virtuais e VTableHerança múltiplaHerança virtualRevisão - Hierarquia de funcionários10Visão geral da STL
Visão geral e filosofia da STLContêineres da STLIteradoresAlgoritmos da STLFunctors e expressões lambdaRecapitulação - Frequência de palavras13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonFactory e Abstract FactoryPadrão BuilderPadrão ObserverPadrão Strategy2Gerenciamento de Memória
Memória Stack vs. HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Ponteiros Inteligentes em C++RAII em C++Revisão - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de acesso em C++Especificadores de acesso em profundidadeOcultação de informaçõesStruct vs ClasseClasses aninhadas e internasRecapitulação - Sistema de registros de alunos8Polimorfismo
Polimorfismo em compilação vs. execuçãoSobrecarga de funçõesFunções virtuais revisadasFunções virtuais purasClasses abstratasDesign de interfaces em C++Conversão dinâmica e RTTIRecapitulação — Calculadora de formas11Conceitos Avançados de OOP
Composição vs. HerançaMixins via CRTPIdioma PimplApagamento de TiposClasses Enum e Tipagem ForteTratamento de Exceções em OOPHierarquias de Exceções Personalizadas14Padrões de Projeto — Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositeRAII como Padrão3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentoListas de Inicialização do ConstrutorConstrutores DelegantesAprofundamento em DestrutoresRegra dos Três / Cinco / ZeroRevisão - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de FluxoSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçõesTemplates de ClassesEspecialização de TemplatesTemplates VariádicosNoções Básicas de SFINAE e Traits de TiposRecapitulação - Contêiner GenéricoPratique por conta própria: Compilador de C++ online