Médio C++

Funcionários e bônus

Enunciado

Crie uma hierarquia de classes para representar funcionários. A classe base Funcionario deve ter um método virtual calcularBonus() const que retorna 0.0 e um método nome() const que retorna o nome. As classes Gerente e Desenvolvedor herdam de Funcionario e sobrescrevem calcularBonus(): Gerente recebe 20% do salário base, Desenvolvedor recebe 10%. Use override e garanta que o destrutor seja virtual. No main, crie um vetor de std::unique_ptr<Funcionario>, adicione um gerente e um desenvolvedor, e imprima o nome e o bônus de cada um.

Requisitos

  • Funcionario tem método virtual double calcularBonus() const que retorna 0.0 e método virtual std::string nome() const.
  • Gerente e Desenvolvedor herdam publicamente de Funcionario e usam override em calcularBonus().
  • O destrutor de Funcionario é virtual.
  • O main usa std::unique_ptr<Funcionario> e chama nome() e calcularBonus() polimorficamente.
  • A saída mostra os nomes e bônus corretos.

Código inicial

#include <iostream>
#include <memory>
#include <string>
#include <vector>

// TODO: definir classes Funcionario, Gerente, Desenvolvedor

int main() {
    // TODO: criar vetor de unique_ptr<Funcionario> e imprimir nome e bônus
    return 0;
}

Saída esperada

Nome: Ana, Bonus: 2000
Nome: Bruno, Bonus: 500
Ver dica

O salário base pode ser passado no construtor de cada classe derivada. Lembre-se de que nome() também pode ser virtual para permitir personalização.

Mostrar solução
#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Funcionario {
protected:
    std::string nome_;
    double salarioBase_;
public:
    Funcionario(std::string nome, double salarioBase)
        : nome_(std::move(nome)), salarioBase_(salarioBase) {}

    virtual double calcularBonus() const {
        return 0.0;
    }

    virtual std::string nome() const {
        return nome_;
    }

    virtual ~Funcionario() = default; // destrutor virtual
};

class Gerente : public Funcionario {
public:
    Gerente(std::string nome, double salarioBase)
        : Funcionario(std::move(nome), salarioBase) {}

    double calcularBonus() const override {
        return salarioBase_ * 0.20;
    }
};

class Desenvolvedor : public Funcionario {
public:
    Desenvolvedor(std::string nome, double salarioBase)
        : Funcionario(std::move(nome), salarioBase) {}

    double calcularBonus() const override {
        return salarioBase_ * 0.10;
    }
};

int main() {
    std::vector<std::unique_ptr<Funcionario>> funcionarios;
    funcionarios.push_back(std::make_unique<Gerente>("Ana", 10000.0));
    funcionarios.push_back(std::make_unique<Desenvolvedor>("Bruno", 5000.0));

    for (const auto& f : funcionarios) {
        std::cout << "Nome: " << f->nome()
                  << ", Bonus: " << f->calcularBonus() << '\n';
    }
    return 0;
}

Passo a passo

  1. A classe Funcionario possui membros protegidos nome_ e salarioBase_, acessíveis pelas classes derivadas. O construtor inicializa esses valores.
  2. O método calcularBonus() é virtual e retorna 0.0 por padrão. Isso permite que as classes derivadas forneçam implementações específicas.
  3. O método nome() também é virtual e retorna o nome armazenado. Embora não seja sobrescrito aqui, poderia ser em outras subclasses.
  4. O destrutor virtual virtual ~Funcionario() = default; garante que ao deletar um objeto via ponteiro para Funcionario, o destrutor da classe derivada seja chamado, liberando recursos corretamente.
  5. A classe Gerente herda publicamente de Funcionario e sobrescreve calcularBonus() com override, retornando 20% do salário base.
  6. A classe Desenvolvedor também herda publicamente e sobrescreve calcularBonus() retornando 10% do salário base.
  7. No main, criamos um std::vector<std::unique_ptr<Funcionario>> e adicionamos um Gerente e um Desenvolvedor com std::make_unique.
  8. Iteramos sobre o vetor e imprimimos o nome e o bônus de cada funcionário. Devido ao polimorfismo, as versões corretas de calcularBonus() são chamadas.

Por que funciona

A herança pública estabelece a relação "é um": Gerente e Desenvolvedor são Funcionario. O método virtual calcularBonus() permite que cada subclasse forneça seu próprio cálculo. O uso de std::unique_ptr<Funcionario> garante que os objetos sejam destruídos corretamente, desde que o destrutor seja virtual. O override assegura que estamos realmente sobrescrevendo o método da base, evitando erros de digitação na assinatura.

Erros comuns

  • Não tornar calcularBonus() virtual: Se não for virtual, a chamada f->calcularBonus() sempre usaria a versão de Funcionario, retornando 0.0. Declare virtual double calcularBonus() const.
  • Esquecer override: Se a assinatura não coincidir (por exemplo, faltar const), o método não sobrescreve e o compilador pode não avisar. Use override para que o compilador verifique.
  • Destrutor não virtual: Se ~Funcionario() não for virtual, ao deletar um Gerente via unique_ptr<Funcionario>, apenas o destrutor de Funcionario seria chamado, causando vazamento de recursos. Declare virtual ~Funcionario() = default;.
  • Acessar membros privados da base: Se nome_ e salarioBase_ fossem privados, as classes derivadas não poderiam acessá-los. Use protected para permitir acesso controlado.

Outra forma de resolver

Poderia-se usar uma função virtual pura (= 0) para tornar Funcionario uma classe abstrata, forçando as subclasses a implementar calcularBonus(). Isso é útil quando não faz sentido instanciar a base. Exemplo: virtual double calcularBonus() const = 0;. No entanto, o enunciado não exige isso.

Saída esperada

Nome: Ana, Bonus: 2000
Nome: Bruno, Bonus: 500