Lista 11 · Polimorfismo e sobrecarga de operadores¶
Exercícios da Semana 13 — Polimorfismo e sobrecarga de operadores.
Como resolver
Copie o bloco de código de cada exercício, cole no seu compilador online, preencha a parte marcada como ESCREVA SUA SOLUCAO AQUI e rode. A saída mostra quais testes passaram.
ex01¶
Dada a classe abstrata Ave (método virtual puro som() const, já declarado), complete Papagaio (deve retornar "Ola!") e Coruja (deve retornar "Uhu!"), ambas sobrescrevendo som().
Papagaio p;
Coruja c;
Ave& a1 = p;
Ave& a2 = c;
a1.som(); // -> "Ola!" (chamada polimorfica -- via referencia de Ave)
a2.som(); // -> "Uhu!"
// ex01 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <string>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX01_H
#define EX01_H
class Ave {
public:
virtual std::string som() const = 0;
virtual ~Ave() {}
};
class Papagaio : public Ave {
public:
std::string som() const override;
};
class Coruja : public Ave {
public:
std::string som() const override;
};
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::string Papagaio::som() const {
// TODO: retorne "Ola!"
return "";
}
std::string Coruja::som() const {
// TODO: retorne "Uhu!"
return "";
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
Papagaio p;
Coruja c;
Ave& a1 = p;
Ave& a2 = c;
assert(a1.som() == std::string("Ola!"));
assert(a2.som() == std::string("Uhu!"));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex02¶
Complete as classes Bicicleta e Carro, que herdam da classe abstrata MeioDeTransporte (método virtual puro tempo_de_viagem(double km) const, que devolve o tempo de viagem em horas). Os construtores já estão implementados; implemente apenas tempo_de_viagem() em cada uma.
Bicicletaguarda umavelocidade_media_em km/h. O tempo é simplesmentekm / velocidade_media_.Carroguarda umavelocidade_media_e umminutos_de_parada_a cada 100 km (parada para abastecer, descansar). O tempo ékm / velocidade_media_mais as paradas: a cada 100 km completos há uma parada. Em 250 km há duas paradas (aos 100 e aos 200 km), e as paradas entram em horas — divida os minutos por60.0.
Repare que as duas classes respondem à mesma pergunta com regras bem diferentes, e que quem chama tempo_de_viagem() por uma referência MeioDeTransporte& não precisa saber qual das duas está do outro lado. É esse o ponto do método virtual puro: a classe base define a pergunta, cada derivada define a resposta.
Para contar as paradas, use divisão inteira: static_cast<int>(km) / 100.
Bicicleta b(20.0); // 20 km/h
b.tempo_de_viagem(50.0); // -> 2.5 (50 / 20)
Carro c(100.0, 30); // 100 km/h, 30 min de parada a cada 100 km
c.tempo_de_viagem(250.0); // -> 3.5 (250/100 = 2.5 h, mais 2 paradas = 1.0 h)
// ex02 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <cmath>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX02_H
#define EX02_H
class MeioDeTransporte {
public:
// Tempo de viagem, em horas, para percorrer a distancia dada em km.
virtual double tempo_de_viagem(double km) const = 0;
virtual ~MeioDeTransporte() {}
};
class Bicicleta : public MeioDeTransporte {
private:
double velocidade_media_; // km/h
public:
explicit Bicicleta(double velocidade_media) : velocidade_media_(velocidade_media) {}
double tempo_de_viagem(double km) const override;
};
class Carro : public MeioDeTransporte {
private:
double velocidade_media_; // km/h
int minutos_de_parada_; // a cada 100 km completos
public:
Carro(double velocidade_media, int minutos_de_parada)
: velocidade_media_(velocidade_media), minutos_de_parada_(minutos_de_parada) {}
double tempo_de_viagem(double km) const override;
};
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
double Bicicleta::tempo_de_viagem(double km) const {
// TODO: retorne km / velocidade_media_.
return 0.0;
}
double Carro::tempo_de_viagem(double km) const {
// TODO: comece com km / velocidade_media_.
// Some as paradas: static_cast<int>(km) / 100 paradas, cada uma
// custando minutos_de_parada_ / 60.0 horas.
return 0.0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
static bool perto(double a, double b) {
return std::fabs(a - b) < 0.0001;
}
int main() {
Bicicleta b(20.0);
assert(perto(b.tempo_de_viagem(50.0), 2.5));
assert(perto(b.tempo_de_viagem(0.0), 0.0));
Carro c(100.0, 30);
// 250 km: 2.5 h de estrada + 2 paradas de 30 min = 3.5 h
assert(perto(c.tempo_de_viagem(250.0), 3.5));
// menos de 100 km: nenhuma parada
assert(perto(c.tempo_de_viagem(80.0), 0.8));
// exatamente 100 km: uma parada completa
assert(perto(c.tempo_de_viagem(100.0), 1.5));
// carro sem paradas se comporta como a bicicleta, so que mais rapido
Carro sem_parada(50.0, 0);
assert(perto(sem_parada.tempo_de_viagem(200.0), 4.0));
// a mesma pergunta, feita pela referencia a classe base
MeioDeTransporte& transporte = c;
assert(perto(transporte.tempo_de_viagem(250.0), 3.5));
MeioDeTransporte& outro = b;
assert(perto(outro.tempo_de_viagem(50.0), 2.5));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex03¶
Complete a classe Duracao, que representa um intervalo de tempo em minutos e segundos (campos minutos_ e segundos_, construtor e getters já dados). Implemente operator+ e operator==.
O operator+ não é apenas somar campo a campo. Somar 1min30s com 2min45s campo a campo daria 3min75s, que não é um jeito válido de escrever uma duração: 75 segundos são 1 minuto e 15 segundos. Depois de somar, normalize o resultado — cada 60 segundos viram 1 minuto a mais, e no fim os segundos ficam entre 0 e 59.
É esse o motivo de sobrecarregar o operador em vez de deixar quem chama somar os campos na mão: a regra de normalização mora dentro da classe, e ninguém consegue construir uma Duracao com 75 segundos somando duas válidas.
O operator== compara as duas durações. Como toda Duracao produzida pelo operator+ já está normalizada, basta comparar os dois campos.
Assuma que quem constrói uma Duracao passa segundos entre 0 e 59.
Duracao a(1, 30); // 1 min 30 s
Duracao b(2, 45); // 2 min 45 s
Duracao c = a + b;
c.minutos(); // -> 4 (e nao 3)
c.segundos(); // -> 15 (e nao 75)
a == b; // -> false
Duracao d(1, 30);
a == d; // -> true
// ex03 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX03_H
#define EX03_H
class Duracao {
private:
int minutos_;
int segundos_;
public:
Duracao(int minutos, int segundos) : minutos_(minutos), segundos_(segundos) {}
int minutos() const { return minutos_; }
int segundos() const { return segundos_; }
Duracao operator+(const Duracao& outra) const;
bool operator==(const Duracao& outra) const;
};
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
Duracao Duracao::operator+(const Duracao& outra) const {
// TODO: some os minutos e os segundos separadamente e depois NORMALIZE:
// cada 60 segundos viram 1 minuto (use / 60 e % 60).
// Devolva um novo Duracao com o resultado ja normalizado.
return Duracao(0, 0);
}
bool Duracao::operator==(const Duracao& outra) const {
// TODO: retorne true se minutos_ e segundos_ forem iguais aos da outra.
return false;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
Duracao a(1, 30);
Duracao b(2, 45);
// 75 segundos precisam virar 1 min e 15 s
Duracao c = a + b;
assert(c.minutos() == 4);
assert(c.segundos() == 15);
// soma que nao precisa de normalizacao
Duracao simples = Duracao(1, 10) + Duracao(2, 20);
assert(simples.minutos() == 3);
assert(simples.segundos() == 30);
// exatamente 60 segundos: vira 1 minuto e 0 segundo
Duracao cheio = Duracao(0, 30) + Duracao(0, 30);
assert(cheio.minutos() == 1);
assert(cheio.segundos() == 0);
// somar zero nao muda nada
Duracao zero(0, 0);
Duracao igual = a + zero;
assert(igual.minutos() == 1);
assert(igual.segundos() == 30);
assert(!(a == b));
Duracao d(1, 30);
assert(a == d);
// a soma normalizada e igual a duracao escrita direto
assert((Duracao(0, 45) + Duracao(0, 45)) == Duracao(1, 30));
// minutos iguais, segundos diferentes: nao sao iguais
assert(!(Duracao(2, 0) == Duracao(2, 1)));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex04¶
Dadas as classes Forma (abstrata), Circulo e Quadrado (todas já implementadas), escreva soma_areas, que recebe um std::vector<std::unique_ptr<Forma>> e devolve a soma das áreas de todas as formas, chamando area() polimorficamente em cada uma.
std::vector<std::unique_ptr<Forma>> formas;
formas.push_back(std::make_unique<Quadrado>(2.0)); // area 4.0
formas.push_back(std::make_unique<Circulo>(1.0)); // area ~3.14159
soma_areas(formas); // -> ~7.14159
// ex04 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <cmath>
#include <vector>
#include <memory>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX04_H
#define EX04_H
class Forma {
public:
virtual double area() const = 0;
virtual ~Forma() {}
};
class Circulo : public Forma {
private:
double raio_;
public:
explicit Circulo(double raio) : raio_(raio) {}
double area() const override { return 3.14159 * raio_ * raio_; }
};
class Quadrado : public Forma {
private:
double lado_;
public:
explicit Quadrado(double lado) : lado_(lado) {}
double area() const override { return lado_ * lado_; }
};
// Soma as areas de todas as formas do vector (chamada polimorfica).
double soma_areas(const std::vector<std::unique_ptr<Forma>>& formas);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
double soma_areas(const std::vector<std::unique_ptr<Forma>>& formas) {
// TODO: percorra "formas" (const auto& forma : formas) somando forma->area().
return 0.0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::vector<std::unique_ptr<Forma>> formas;
formas.push_back(std::make_unique<Quadrado>(2.0));
formas.push_back(std::make_unique<Circulo>(1.0));
assert(std::abs((soma_areas(formas)) - (7.14159)) <= (0.001));
std::vector<std::unique_ptr<Forma>> vazio;
assert(std::abs((soma_areas(vazio)) - (0.0)) <= (0.0001));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex05¶
Complete os destrutores de Conexao e ConexaoSegura (ConexaoSegura herda de Conexao, acrescentando a camada de criptografia). Cada destrutor deve fazer duas coisas:
- incrementar o seu próprio contador estático (
Conexao::destruicoeseConexaoSegura::destruicoes); - acrescentar a sua letra ao registro estático
Conexao::ordem—"C"no destrutor deConexaoe"S"no deConexaoSegura.
O contador prova que os dois destrutores rodaram. O registro ordem prova em que sequência eles rodaram, e é aí que está a lição: ao destruir um ConexaoSegura, o C++ chama primeiro o destrutor da derivada e depois o da base, de dentro para fora. Faz sentido — a camada de criptografia precisa ser desmontada antes de a conexão de baixo ser fechada, e não depois. O resultado esperado é "SC", nunca "CS".
O destrutor de Conexao já é virtual — isso é proposital, e é o que garante que delete num ponteiro Conexao* apontando para um ConexaoSegura chame os dois destrutores. Sem o virtual, só o de Conexao rodaria: o registro sairia "C" e a camada de cima vazaria.
Conexao::destruicoes = 0;
ConexaoSegura::destruicoes = 0;
Conexao::ordem = "";
Conexao* c = new ConexaoSegura();
delete c; // ~ConexaoSegura() PRIMEIRO, depois ~Conexao()
Conexao::destruicoes; // -> 1
ConexaoSegura::destruicoes; // -> 1
Conexao::ordem; // -> "SC"
// ex05 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <string>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX05_H
#define EX05_H
class Conexao {
public:
static inline int destruicoes = 0;
// Registro da ordem em que os destrutores rodaram:
// "C" para ~Conexao(), "S" para ~ConexaoSegura().
static inline std::string ordem = "";
virtual ~Conexao();
};
class ConexaoSegura : public Conexao {
public:
static inline int destruicoes = 0;
~ConexaoSegura() override;
};
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
Conexao::~Conexao() {
// TODO: incremente Conexao::destruicoes e acrescente "C" a Conexao::ordem.
}
ConexaoSegura::~ConexaoSegura() {
// TODO: incremente ConexaoSegura::destruicoes e acrescente "S" a Conexao::ordem.
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
// destruindo pelo ponteiro para a base: o ~Conexao() virtual e o que
// faz o destrutor da derivada ser chamado tambem
Conexao::destruicoes = 0;
ConexaoSegura::destruicoes = 0;
Conexao::ordem = "";
Conexao* c = new ConexaoSegura();
delete c;
assert(Conexao::destruicoes == 1);
assert(ConexaoSegura::destruicoes == 1);
assert(Conexao::ordem == "SC"); // de dentro para fora, nunca "CS"
// objeto na pilha: mesma ordem
Conexao::destruicoes = 0;
ConexaoSegura::destruicoes = 0;
Conexao::ordem = "";
{
ConexaoSegura s;
}
assert(Conexao::destruicoes == 1);
assert(ConexaoSegura::destruicoes == 1);
assert(Conexao::ordem == "SC");
// uma Conexao pura destroi so a si mesma
Conexao::destruicoes = 0;
ConexaoSegura::destruicoes = 0;
Conexao::ordem = "";
{
Conexao simples;
}
assert(Conexao::destruicoes == 1);
assert(ConexaoSegura::destruicoes == 0);
assert(Conexao::ordem == "C");
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex06¶
Dada a classe base Dispositivo (campos protegidos modelo_ e armazenamento_gb_, construtor e getters já implementados, e detalhes() virtual já implementado na base), complete as duas classes derivadas:
Notebook— tem também umsistema_operacional_. Seudetalhes()deve devolver o texto da base seguido de" | SO: <sistema operacional>".Tablet— tem também umbool tem_5g_. Seudetalhes()deve devolver o texto da base seguido de" | 5G: Sim"ou" | 5G: Nao".
Repare que a versão da base continua útil: em vez de repetir a montagem do texto, chame Dispositivo::detalhes() e concatene o resto.
Notebook n("Dell XPS 13", 512, "Linux");
n.detalhes(); // -> "Dell XPS 13 | 512 GB | SO: Linux"
Tablet t("iPad", 64, false);
t.detalhes(); // -> "iPad | 64 GB | 5G: Nao"
// ex06 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX06_H
#define EX06_H
class Dispositivo {
protected:
std::string modelo_;
int armazenamento_gb_;
public:
Dispositivo(const std::string& modelo, int armazenamento_gb)
: modelo_(modelo), armazenamento_gb_(armazenamento_gb) {}
virtual ~Dispositivo() = default;
std::string modelo() const { return modelo_; }
int armazenamento_gb() const { return armazenamento_gb_; }
virtual std::string detalhes() const {
return modelo_ + " | " + std::to_string(armazenamento_gb_) + " GB";
}
};
class Notebook : public Dispositivo {
private:
std::string sistema_operacional_;
public:
Notebook(const std::string& modelo, int armazenamento_gb,
const std::string& sistema_operacional)
: Dispositivo(modelo, armazenamento_gb),
sistema_operacional_(sistema_operacional) {}
std::string detalhes() const override;
};
class Tablet : public Dispositivo {
private:
bool tem_5g_;
public:
Tablet(const std::string& modelo, int armazenamento_gb, bool tem_5g)
: Dispositivo(modelo, armazenamento_gb), tem_5g_(tem_5g) {}
std::string detalhes() const override;
};
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::string Notebook::detalhes() const {
// TODO: devolva Dispositivo::detalhes() + " | SO: " + sistema_operacional_.
return "";
}
std::string Tablet::detalhes() const {
// TODO: devolva Dispositivo::detalhes() + " | 5G: Sim" ou " | 5G: Nao",
// conforme o valor de tem_5g_.
return "";
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
Notebook n("Dell XPS 13", 512, "Linux");
assert(n.detalhes() == std::string("Dell XPS 13 | 512 GB | SO: Linux"));
Tablet com_5g("Galaxy Tab", 128, true);
assert(com_5g.detalhes() == std::string("Galaxy Tab | 128 GB | 5G: Sim"));
Tablet sem_5g("iPad", 64, false);
assert(sem_5g.detalhes() == std::string("iPad | 64 GB | 5G: Nao"));
// A base continua funcionando como base.
Dispositivo generico("Generico", 32);
assert(generico.detalhes() == std::string("Generico | 32 GB"));
// Chamado por ponteiro da base, cada objeto usa a sua propria versao.
std::vector<std::unique_ptr<Dispositivo>> aparelhos;
aparelhos.push_back(std::make_unique<Notebook>("Dell XPS 13", 512, "Linux"));
aparelhos.push_back(std::make_unique<Tablet>("iPad", 64, false));
assert(aparelhos[0]->detalhes() == std::string("Dell XPS 13 | 512 GB | SO: Linux"));
assert(aparelhos[1]->detalhes() == std::string("iPad | 64 GB | 5G: Nao"));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex07¶
Dada a classe abstrata Produto (campos protegidos nome_ e preco_, construtor e getters já implementados, método virtual puro calcula_desconto() const), complete as duas classes derivadas:
ProdutoEletronico— desconto de 10% do preço se o preço for maior que1000.0; 5% caso contrário.ProdutoAlimenticio— tem tambémdias_para_expirar_. Desconto de 20% do preço se faltarem 5 dias ou menos para expirar; 10% caso contrário.
Note que as duas devolvem o valor do desconto, não o preço com desconto.
ProdutoEletronico tv("TV", 2000.0);
tv.calcula_desconto(); // -> 200.0
ProdutoAlimenticio leite("Leite", 10.0, 3);
leite.calcula_desconto(); // -> 2.0
// ex07 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <memory>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX07_H
#define EX07_H
class Produto {
protected:
std::string nome_;
double preco_;
public:
Produto(const std::string& nome, double preco) : nome_(nome), preco_(preco) {}
virtual ~Produto() = default;
std::string nome() const { return nome_; }
double preco() const { return preco_; }
// Retorna o VALOR do desconto (nao o preco ja descontado).
virtual double calcula_desconto() const = 0;
};
class ProdutoEletronico : public Produto {
public:
ProdutoEletronico(const std::string& nome, double preco) : Produto(nome, preco) {}
double calcula_desconto() const override;
};
class ProdutoAlimenticio : public Produto {
private:
int dias_para_expirar_;
public:
ProdutoAlimenticio(const std::string& nome, double preco, int dias_para_expirar)
: Produto(nome, preco), dias_para_expirar_(dias_para_expirar) {}
double calcula_desconto() const override;
};
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
double ProdutoEletronico::calcula_desconto() const {
// TODO: 10% de preco_ se preco_ > 1000.0; 5% caso contrario.
return 0.0;
}
double ProdutoAlimenticio::calcula_desconto() const {
// TODO: 20% de preco_ se dias_para_expirar_ <= 5; 10% caso contrario.
return 0.0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
ProdutoEletronico tv("TV", 2000.0);
assert(std::abs((tv.calcula_desconto()) - (200.0)) <= (0.0001));
ProdutoEletronico fone("Fone", 200.0);
assert(std::abs((fone.calcula_desconto()) - (10.0)) <= (0.0001));
// Exatamente 1000 nao passa do limite: fica nos 5%.
ProdutoEletronico limite("Monitor", 1000.0);
assert(std::abs((limite.calcula_desconto()) - (50.0)) <= (0.0001));
ProdutoAlimenticio leite("Leite", 10.0, 3);
assert(std::abs((leite.calcula_desconto()) - (2.0)) <= (0.0001));
// Exatamente 5 dias ainda conta como "perto de expirar".
ProdutoAlimenticio queijo("Queijo", 50.0, 5);
assert(std::abs((queijo.calcula_desconto()) - (10.0)) <= (0.0001));
ProdutoAlimenticio arroz("Arroz", 20.0, 90);
assert(std::abs((arroz.calcula_desconto()) - (2.0)) <= (0.0001));
// Todos somados por ponteiro da base.
std::vector<std::unique_ptr<Produto>> carrinho;
carrinho.push_back(std::make_unique<ProdutoEletronico>("TV", 2000.0));
carrinho.push_back(std::make_unique<ProdutoAlimenticio>("Leite", 10.0, 3));
double total = 0.0;
for (const auto& p : carrinho) {
total += p->calcula_desconto();
}
assert(std::abs((total) - (202.0)) <= (0.0001));
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex08¶
Sistema de triagem de chamados de suporte técnico. Dada a classe abstrata Chamado (campos protegidos id_ e descricao_, construtor e getters já implementados, método virtual puro processar() const), complete as duas classes derivadas:
ChamadoHardware— se a descrição contiver as duas palavras"impressora"e"papel", devolve"Verificar papel preso na impressora". Caso contrário, devolve"Encaminhar para suporte de hardware".ChamadoSoftware— se a descrição contiver as duas palavras"erro"e"instalacao", devolve"Realizar reinstalacao do software". Caso contrário, devolve"Encaminhar para suporte de software".
Use descricao_.find("palavra") != std::string::npos para testar se a palavra aparece. Considere que as descrições vêm em minúsculas e sem acento.
ChamadoHardware c(1, "a impressora esta com papel preso");
c.processar(); // -> "Verificar papel preso na impressora"
// ex08 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX08_H
#define EX08_H
class Chamado {
protected:
int id_;
std::string descricao_;
public:
Chamado(int id, const std::string& descricao) : id_(id), descricao_(descricao) {}
virtual ~Chamado() = default;
int id() const { return id_; }
std::string descricao() const { return descricao_; }
// Retorna a orientacao de atendimento para este chamado.
virtual std::string processar() const = 0;
};
class ChamadoHardware : public Chamado {
public:
ChamadoHardware(int id, const std::string& descricao) : Chamado(id, descricao) {}
std::string processar() const override;
};
class ChamadoSoftware : public Chamado {
public:
ChamadoSoftware(int id, const std::string& descricao) : Chamado(id, descricao) {}
std::string processar() const override;
};
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
std::string ChamadoHardware::processar() const {
// TODO: se descricao_ contiver "impressora" E "papel", devolva
// "Verificar papel preso na impressora".
// Caso contrario, "Encaminhar para suporte de hardware".
return "";
}
std::string ChamadoSoftware::processar() const {
// TODO: se descricao_ contiver "erro" E "instalacao", devolva
// "Realizar reinstalacao do software".
// Caso contrario, "Encaminhar para suporte de software".
return "";
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
ChamadoHardware preso(1, "a impressora esta com papel preso");
assert(preso.processar() == std::string("Verificar papel preso na impressora"));
// So uma das duas palavras nao basta.
ChamadoHardware so_impressora(2, "a impressora nao liga");
assert(so_impressora.processar() == std::string("Encaminhar para suporte de hardware"));
ChamadoHardware outro(3, "monitor com listras");
assert(outro.processar() == std::string("Encaminhar para suporte de hardware"));
ChamadoSoftware reinstalar(4, "erro durante a instalacao do sistema");
assert(reinstalar.processar() == std::string("Realizar reinstalacao do software"));
ChamadoSoftware so_erro(5, "erro ao abrir o programa");
assert(so_erro.processar() == std::string("Encaminhar para suporte de software"));
// A fila de triagem trata todos pela classe base.
std::vector<std::unique_ptr<Chamado>> fila;
fila.push_back(std::make_unique<ChamadoHardware>(6, "papel preso na impressora"));
fila.push_back(std::make_unique<ChamadoSoftware>(7, "nao consigo entrar"));
assert(fila[0]->processar() == std::string("Verificar papel preso na impressora"));
assert(fila[1]->processar() == std::string("Encaminhar para suporte de software"));
assert(fila[0]->id() == 6);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex09¶
Dadas as classes Forma (abstrata), Circulo e Quadrado — todas já implementadas —, escreva indice_maior_area, que recebe um std::vector<std::unique_ptr<Forma>> e devolve o índice da forma de maior área, ou -1 se o vector estiver vazio. Em caso de empate, devolva o índice da primeira.
É a busca do melhor até agora da Lista 05, com uma diferença: o valor comparado não está guardado em lugar nenhum — ele vem de formas[i]->area(), uma chamada polimórfica que só se resolve em tempo de execução. A função não sabe, e não precisa saber, quais tipos de forma existem.
Vale o mesmo cuidado de sempre: comece pelo índice 0, e não por uma área inicial 0.
// ex09 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <vector>
#include <memory>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX09_H
#define EX09_H
class Forma {
public:
virtual double area() const = 0;
virtual ~Forma() = default;
};
class Circulo : public Forma {
private:
double raio_;
public:
explicit Circulo(double raio) : raio_(raio) {}
double area() const override { return 3.14159 * raio_ * raio_; }
};
class Quadrado : public Forma {
private:
double lado_;
public:
explicit Quadrado(double lado) : lado_(lado) {}
double area() const override { return lado_ * lado_; }
};
// Retorna o indice da forma de MAIOR area, ou -1 se o vector
// estiver vazio. Em caso de empate, devolve o indice da primeira.
int indice_maior_area(const std::vector<std::unique_ptr<Forma>>& formas);
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
int indice_maior_area(const std::vector<std::unique_ptr<Forma>>& formas) {
// TODO: e a busca do melhor ate agora da Lista 05, so que o valor comparado
// vem de uma chamada polimorfica: formas[i]->area().
// Comece pelo indice 0 (nao por area 0) e trate o vector vazio.
return -1;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
std::vector<std::unique_ptr<Forma>> formas;
formas.push_back(std::make_unique<Quadrado>(2.0)); // area 4
formas.push_back(std::make_unique<Circulo>(3.0)); // area ~28.3
formas.push_back(std::make_unique<Quadrado>(1.0)); // area 1
assert(indice_maior_area(formas) == 1);
std::vector<std::unique_ptr<Forma>> uma;
uma.push_back(std::make_unique<Quadrado>(5.0));
assert(indice_maior_area(uma) == 0);
// empate: fica a primeira
std::vector<std::unique_ptr<Forma>> empate;
empate.push_back(std::make_unique<Quadrado>(2.0));
empate.push_back(std::make_unique<Quadrado>(2.0));
assert(indice_maior_area(empate) == 0);
std::vector<std::unique_ptr<Forma>> vazio;
assert(indice_maior_area(vazio) == -1);
std::cout << "Todos os testes passaram!\n";
return 0;
}
ex10¶
Dada a classe abstrata Funcionario (método virtual puro salario() const e destrutor virtual, já declarados), complete Vendedor (salário fixo de 1500.0 mais 100.0 por venda registrada no construtor) e Gerente (salário fixo de 4000.0, sem variação).
O último caso de teste é o que importa: a chamada através de Funcionario& precisa executar a versão da classe concreta. É para isso que o salario() da base é virtual.
Vendedor v(3); // 3 vendas
v.salario(); // -> 1500.0 + 3*100.0 = 1800.0
Gerente g;
g.salario(); // -> 4000.0
Funcionario& f = v;
f.salario(); // -> 1800.0 (chamada polimorfica)
// ex10 — versao de arquivo unico (gerada automaticamente,
// nao edite este arquivo direto: edite os fontes em exercicios/ e rode
// tools/gerar_single.py --todos de novo).
//
// Cole este arquivo inteiro no seu compilador online e rode.
#include <cassert>
#include <iostream>
#include <cmath>
// ============================================================
// Declaracoes do exercicio
// ============================================================
#ifndef EX10_H
#define EX10_H
class Funcionario {
public:
virtual double salario() const = 0;
virtual ~Funcionario() {}
};
class Vendedor : public Funcionario {
private:
int vendas_;
public:
explicit Vendedor(int vendas) : vendas_(vendas) {}
double salario() const override;
};
class Gerente : public Funcionario {
public:
double salario() const override;
};
#endif
// ============================================================
// ESCREVA SUA SOLUCAO AQUI
// ============================================================
double Vendedor::salario() const {
// TODO: retorne 1500.0 + 100.0 * vendas_.
return 0.0;
}
double Gerente::salario() const {
// TODO: retorne 4000.0.
return 0.0;
}
// ============================================================
// NAO ALTERE — testes
// ============================================================
int main() {
Vendedor v(3);
assert(std::abs((v.salario()) - (1800.0)) <= (0.0001));
Gerente g;
assert(std::abs((g.salario()) - (4000.0)) <= (0.0001));
Funcionario& f = v;
assert(std::abs((f.salario()) - (1800.0)) <= (0.0001));
std::cout << "Todos os testes passaram!\n";
return 0;
}