#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
};
class B : public A {
public:
B() { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
};
int main() {
B obj;
}
Qual será a saída?
a) B()
b) A()
c) ~B() ~A()
d) A()
B()
~B()
~A()
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
};
class B : public A {
public:
B() { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
};
int main() {
B obj;
}
a) B()
b) A()
c) ~B() ~A()
d) A()
B()
~B()
~A()
Passo 1
O enunciado pede para determinar a saída (o que aparece no terminal) ao executar o programa C++ abaixo. Informações relevantes do enunciado e do código:
- Temos duas classes:
AeB, ondeBherda publicamente deA. - A classe
Atem um construtor que imprimeA()e um destrutor que imprime~A(). - A classe
Btem um construtor que imprimeB()e um destrutor que imprime~B(). - No
mainé criado um objeto automático (local) de tipoBchamadoobjcom a linhaB obj;. - O programa não faz mais nada além disso, então devemos considerar a criação do objeto e o término do
mainpara saber quais mensagens são impressas e em que ordem.
Passo 2
Conceito: o que são construtores e destrutores e quando são chamados.
- Construtor: é um método que é executado automaticamente quando um objeto é criado. Serve para inicializar o objeto. No nosso código, os construtores imprimem texto para demonstrar sua chamada.
- Destrutor: é um método que é executado automaticamente quando um objeto é destruído (quando sai de escopo ou é deleteado). No nosso código, os destrutores imprimem texto para demonstrar sua chamada.
- Para objetos automáticos (como
objdentro demain), o construtor é chamado no ponto de criação (linhaB obj;) e o destrutor é chamado quando o objeto sai de escopo — aqui, no final da funçãomain, antes demainterminar.
Passo 3
Conceito: ordem de chamadas em herança para construtores e destrutores.
- Ao construir um objeto de uma classe derivada, primeiro são executados os construtores das classes base (da mais “alta” na hierarquia para a mais derivada), depois o construtor da classe mais derivada. Isso garante que a parte base do objeto esteja inicializada antes da parte derivada usar essa base.
- Ao destruir um objeto, a ordem é inversa: primeiro é executado o destrutor da classe derivada, depois os destrutores das classes base (da mais derivada para a mais base). Isso evita que a parte derivada tente usar recursos da base já liberados.
Passo 4
Aplicando a regra de ordem ao nosso código:
- Estamos criando um objeto do tipo
B. A classeBherda deA. Então, na construção:- Primeiro o construtor de
Aé chamado — esse imprimeA(). - Depois o construtor de
Bé chamado — esse imprimeB().
- Primeiro o construtor de
- Quando
maintermina eobjsai do escopo, ocorre a destruição:- Primeiro o destrutor de
Bé chamado — imprime~B(). - Depois o destrutor de
Aé chamado — imprime~A().
- Primeiro o destrutor de
Passo 5
Sequência temporal completa das impressões:
- Na criação do objeto (
B obj;): apareceA()entãoB(). - No final de
main, ao destruir o objeto: aparece~B()então~A().
Passo 6
Pequena observação prática (para a prova): quando você vir código com herança e quiser saber a ordem de prints de construtores/destrutores, aplique a regra “construção: base → derivada” e “destruição: derivada → base”. Isso resolve a maioria dessas questões rapidamente.
Resposta
A()
B()
~B()
~A()
B()
~B()
~A()