#include <iostream>
using namespace std;
class Base {
public:
virtual void f() { cout << "Base" << endl; }
};
class Derivada : public Base {
public:
void f() override { cout << "Derivada" << endl; }
void g() { cout << "Método exclusivo da derivada" << endl; }
};
int main() {
Base* b = new Derivada();
Derivada* d = (Derivada*)b;
d->g();
}
O que o código acima imprime?
a) Base
b) Método exclusivo
c) Derivada
d) Nada.
#include <iostream>
using namespace std;
class Base {
public:
virtual void f() { cout << "Base" << endl; }
};
class Derivada : public Base {
public:
void f() override { cout << "Derivada" << endl; }
void g() { cout << "Método exclusivo da derivada" << endl; }
};
int main() {
Base* b = new Derivada();
Derivada* d = (Derivada*)b;
d->g();
}
a) Base
b) Método exclusivo
c) Derivada
d) Nada.
Passo 1
O enunciado pergunta qual a saída (o que é impresso) pelo programa C++ dado. Informações relevantes do enunciado (extraídas diretamente do código fornecido):
- Existe a classe
Baseque tem um método virtualf()que imprime"Base". - Existe a classe
Derivadaque herda publicamente deBase, sobrescrevef()comoverridee imprime"Derivada", e possui um métodog()que imprime"Método exclusivo da derivada". - No
main():- É criada dinamicamente uma instância com
new Derivada()e o ponteiro retornado é armazenado emBase* b. - Em seguida há um cast:
Derivada* d = (Derivada*)b;(cast em estilo C). - Finalmente chama-se
d->g();.
- É criada dinamicamente uma instância com
- As alternativas oferecidas são:
- a) Base
- b) Método exclusivo
- c) Derivada
- d) Nada
Passo 2
Entender o que significa
Base* b = new Derivada();. Explicação didática e sem pular etapas:new Derivada()cria um objeto cujo tipo dinâmico (o tipo real da instância em tempo de execução) éDerivada.- O ponteiro
btem tipo estáticoBase*, isto é, a variável que armazena o endereço é do tipo ponteiro paraBase. - Em C++ é perfeitamente normal armazenar o endereço de um objeto derivado em um ponteiro para a classe base (polimorfismo). Nesse caso,
baponta para um objetoDerivada, mesmo que a variável seja do tipoBase*. - Consequência prática: o objeto alocado tem a parte da classe
Basee também a parte específica deDerivada.
Passo 3
Explicar o cast
Derivada* d = (Derivada*)b; e as implicações:- O cast em estilo C
(Derivada*)btenta converter o ponteirob(tipoBase*) paraDerivada*. - Em C++ moderno o comportamento recomendado para downcast seguro é
dynamic_cast<Derivada*>(b)(que verifica em tempo de execução sebaponta realmente para umDerivadaquando a classe é polimórfica). O cast em C-style pode equivaler a umstatic_castou a umreinterpret_castdependendo do caso — e pode ser perigoso se usado de forma incorreta. - No entanto, aqui sabemos pelo código que o objeto real criado com
newé de fato umDerivada. Assim, o cast resulta em um ponteirodque aponta para o mesmo objetoDerivada. Nesse cenário particular, o cast é efetivamente seguro e definido (não causa comportamento indefinido) porque o objeto é realmente da classeDerivada. - Resumindo: após o cast,
daponta para a instância deDerivadaque foi criada.
Passo 4
Explicar o que acontece ao chamar
d->g();:g()é um método que só existe na classeDerivada(não está presente emBase).- Como
dé umDerivada*apontando para um objetoDerivada, a chamadad->g()é válida e invoca o método definido emDerivada. - O corpo de
g()fazcout << "Método exclusivo da derivada" << endl;, então a chamada imprime exatamente essa sequência de caracteres seguida de nova linha. - Nota didática: se
btivesse apontado para um objeto que realmente fosse apenasBase(por exemplo,new Base()), o cast paraDerivada*seria inválido e usard->g()causaria comportamento indefinido (possível crash). Por isso odynamic_castcom checagem é mais seguro quando a origem não é garantida.
Passo 5
Esclarecer por que as outras possíveis saídas não ocorrem:
- Alternativa (a)
"Base"corresponderia a uma chamada def()que resolvesse paraBase. O código não chamaf()em lugar algum, então"Base"não é impresso. - Alternativa (c)
"Derivada"seria impressa se o programa chamassef()em um ponteiro paraBaseque referisse um objetoDerivada(por causa dovirtuale dooverride), mas novamentef()não é chamado no programa. - Alternativa (d)
"Nada"significaria que nada é impresso. Não é o caso porqued->g()imprime uma string comcout. - Portanto a saída real é a impressão feita por
g():"Método exclusivo da derivada".
Resposta
b) Método exclusivo da derivada