C++: Noções Básicas de Herança
Última atualização: 2026-08-26
Imagine que você escreveu classes
StudenteTeacher, e percebeu que ambas têm nome e idade, mas estudantes têm matrícula e professores têm número de funcionário.Você pode reutilizar o código da classe
Person? Herança faz exatamente isso — criando um relacionamento "pai-filho" entre classes.
1. O que é Herança?
(1) 1.1 Herança no Dia a Dia
| Exemplo do Dia a Dia | Equivalente no Programa |
|---|---|
| Um filho herda características dos pais (cor dos olhos, altura, etc.) | Uma classe derivada herda membros de sua classe base |
| Um filho pode ter suas próprias características (como talentos especiais) | Uma classe derivada pode adicionar novos membros |
A essência da herança: Criar novas classes estendendo classes existentes.
(2) 1.2 Por que Precisamos de Herança?
Sem herança (código duplicado):
▶ Exemplo 2: Exemplo de Código (Dificuldade ⭐)
#include <iostream>
#include <string>
// Classe Student
class Student {
std::string name;
int age;
std::string studentId;
};
// Classe Teacher
class Teacher {
std::string name; // ❌ Duplicado
int age; // ❌ Duplicado
std::string teacherId;
};
Saída:
(program output)
Com herança (reutilização de código):
#include <iostream>
#include <string>
// Classe base (classe pai)
class Person {
public:
std::string name;
int age;
};
// Classe derivada (classe filho)
class Student : public Person {
public:
std::string studentId; // Novo membro
};
class Teacher : public Person {
public:
std::string teacherId; // Novo membro
};
2. Sintaxe Básica de Herança
(1) 2.1 Declarando uma Classe Derivada
Sintaxe:
class DerivedClassName : inheritanceMode BaseClassName {
// novos membros
};
Exemplo:
#include <iostream>
#include <string>
class Person {
public:
std::string name;
int age;
};
// Student herda de Person
class Student : public Person {
public:
std::string studentId;
};
int main() {
Student s1;
s1.name = "Alice"; // ✅ name herdado
s1.age = 20; // ✅ age herdado
s1.studentId = "2024001"; // Membro próprio
std::cout << "Nome: " << s1.name << std::endl;
std::cout << "Idade: " << s1.age << std::endl;
std::cout << "Matrícula: " << s1.studentId << std::endl;
return 0;
}
3. Modos de Herança (Controle de Acesso)
(1) 3.1 Três Modos de Herança
| Membro da Classe Base \ Modo de Herança | Herança public | Herança protected | Herança private |
|---|---|---|---|
| membros public | public (inalterado) | protected | private |
| membros protected | protected | protected | private |
| membros private | Não acessível | Não acessível | Não acessível |
💡 Ponto Importante: O modo de herança mais usado é a herança public.
(2) 3.2 Herança public (Recomendada)
#include <iostream>
#include <string>
class Person {
private:
std::string id; // Membro privado: não acessível pela classe derivada
protected:
std::string address; // Membro protegido: acessível pela classe derivada
public:
std::string name; // Membro público: acessível por todos
void introduce() {
std::cout << "Meu nome é " << name << std::endl;
}
};
class Student : public Person {
public:
void setAddress(const std::string& addr) {
address = addr; // ✅ Pode acessar membro protegido
// id = "123"; // ❌ Não pode acessar membro privado
}
};
int main() {
Student s1;
s1.name = "Alice"; // ✅ Acessível
// s1.address = "Wuhan"; // ❌ Não acessível (protegido)
return 0;
}
4. Construtores e Herança
(1) 4.1 Ordem de Chamada do Construtor da Classe Derivada
Regra: O construtor da classe base é chamado primeiro, depois o construtor da classe derivada.
#include <iostream>
#include <string>
class Person {
public:
Person() {
std::cout << "Construtor Person" << std::endl;
}
};
class Student : public Person {
public:
Student() {
std::cout << "Construtor Student" << std::endl;
}
};
int main() {
Student s1;
return 0;
}
💡 Ponto Importante: A ordem de chamada do destrutor é invertida — o destrutor da classe derivada é chamado primeiro, depois o da classe base.
5. Prática: Sistema Simples de Gerenciamento de Estudantes (Versão com Herança)
▶ Exemplo 1: Implementação Usando Herança (Dificuldade ⭐⭐)
#include <iostream>
#include <string>
// Classe base
class Person {
protected:
std::string name;
int age;
public:
Person(const std::string& n, int a) : name(n), age(a) {}
void introduce() {
std::cout << "Nome: " << name << ",Idade: " << age << std::endl;
}
};
// Classe derivada: Student
class Student : public Person {
private:
std::string studentId;
double score;
public:
Student(const std::string& n, int a, const std::string& id, double s)
: Person(n, a), studentId(id), score(s) {}
void introduce() {
Person::introduce(); // Chamar introduce da classe base
std::cout << "Matrícula: " << studentId << ",Nota: " << score << std::endl;
}
};
int main() {
Student s1("Alice", 20, "2024001", 92.5);
s1.introduce();
return 0;
}
Saída:
Nome: Alice,Idade: 20
Matrícula: 2024001,Nota: 92.5
❓ Perguntas Frequentes
P: Por que uma classe derivada não pode acessar os membros private da classe base? R: Isso é um requisito de encapsulamento — a classe base pode ocultar detalhes de implementação e expor apenas a interface.
Se uma classe derivada precisa acessar membros da classe base, declare-os como
protected.
P: Quais são os modos de herança? Qual devo usar? R: > - Herança
public: mais usada, preserva a interface da classe base > - Herançaprotected: raramente usada > - Herançaprivate: raramente usadaRecomendação: Sempre use herança
public.
P: Construtores da classe base podem ser herdados? R: Não. Classes derivadas devem definir seus próprios construtores e chamar o construtor da classe base na lista de inicialização.
CPPStudent(const std::string& n, int a) : Person(n, a) {} // Correto
▶ Exemplo 3: Construtor de Classe Derivada (Dificuldade ⭐)
#include <iostream>
#include <string>
class Animal {
protected:
std::string name;
public:
Animal(std::string n) : name(n) {}
void speak() { std::cout << name << "faz um som" << std::endl; }
};
class Dog : public Animal {
public:
Dog(std::string n) : Animal(n) {}
void speak() { std::cout << name << "late" << std::endl; }
};
int main() {
Dog dog("Wangcai");
dog.speak();
return 0;
}
Saída:
Wangcailate
📖 Resumo
- Herança permite que classes derivadas reutilzem código da classe base
- Herança public é a mais usada
- Classes derivadas não podem acessar membros
privateda classe base - Classes derivadas podem acessar membros
protectedda classe base - Ordem de chamada do construtor: classe base → classe derivada
📝 Exercícios
-
Básico (Dificuldade ⭐): Defina uma classe base
Animalcom um membroname. Faça as classesDogeCatherdarem dela. -
Intermediário (Dificuldade ⭐⭐): Estenda o programa acima adicionando uma função virtual
void speak()aAnimal(você aprenderá sobre funções virtuais depois), e façaDogeCatsobrescrevê-la. -
Desafio (Dificuldade ⭐⭐⭐): Projete uma hierarquia de classes para um sistema de gerenciamento de biblioteca:
-
Person(nome, idade) -
Studentherda dePerson(matrícula, número de livros emprestados) -
Teacherherda dePerson(número de funcionário, número de livros emprestados) -
Implemente funcionalidade de empréstimo e devolução.
-
Herança: classes derivadas têm todos os membros da classe base
- Herança public/protected/private controla permissões de acesso
- Construtores de classes derivadas chamam construtores da classe base
- Relacionamento é-um: uma classe derivada é um tipo de classe base
- Herança em diamante requer herança virtual para resolver ambiguidade
6. 🚀 Próximos Passos
Agora que você aprendeu o básico de herança, vamos avançar para Polimorfismo (Aula 32) — permitindo que ponteiros da classe base chamem funções da classe derivada para "uma interface, múltiplas implementações"!