Desafio C++
Classe Livro com múltiplos construtores e validação
Enunciado
Implemente uma classe Livro com membros privados std::string titulo, std::string autor e int ano. Forneça três construtores: um padrão que inicializa com valores vazios/zero, um que recebe título e autor (ano = 0), e um que recebe todos os parâmetros. Adicione um método público exibir() que imprime os dados formatados. Inclua um método setAno(int ano) que só aceita anos maiores ou iguais a 0; caso contrário, mantém o valor anterior. No main, crie três livros usando cada construtor, exiba-os, altere o ano de um deles e exiba novamente.
Requisitos
- A classe deve ter os membros
titulo,autoreanocomoprivate. - Devem existir três construtores sobrecarregados: padrão, com título e autor, e com todos os parâmetros.
- O método
setAnodeve validar se o ano é >= 0 e ignorar valores negativos. - O método
exibirdeve mostrar os dados no formatoTitulo: <titulo>, Autor: <autor>, Ano: <ano>. - A saída deve refletir as alterações feitas no
main.
Código inicial
#include <iostream>
#include <string>
class Livro {
// complete aqui
};
int main() {
// crie três livros e teste
return 0;
}
Saída esperada
Livro 1: Titulo: Desconhecido, Autor: Desconhecido, Ano: 0
Livro 2: Titulo: 1984, Autor: George Orwell, Ano: 0
Livro 3: Titulo: Dom Casmurro, Autor: Machado de Assis, Ano: 1899
Apos alteracao:
Livro 3: Titulo: Dom Casmurro, Autor: Machado de Assis, Ano: 1900
Ver dica
Use this-> nos construtores e no setAno. O construtor padrão pode chamar outro construtor (delegating constructor) ou usar valores padrão.
Mostrar solução
#include <iostream>
#include <string>
class Livro {
private:
std::string titulo;
std::string autor;
int ano;
public:
// Construtor padrão
Livro() : titulo("Desconhecido"), autor("Desconhecido"), ano(0) {}
// Construtor com título e autor
Livro(const std::string& titulo, const std::string& autor)
: titulo(titulo), autor(autor), ano(0) {}
// Construtor completo
Livro(const std::string& titulo, const std::string& autor, int ano) {
this->titulo = titulo;
this->autor = autor;
this->ano = ano;
}
// Valida e altera o ano
void setAno(int ano) {
if (ano >= 0) {
this->ano = ano;
}
}
// Exibe os dados formatados
void exibir() const {
std::cout << "Titulo: " << titulo
<< ", Autor: " << autor
<< ", Ano: " << ano << "\n";
}
};
int main() {
Livro l1; // construtor padrão
Livro l2("1984", "George Orwell"); // título e autor
Livro l3("Dom Casmurro", "Machado de Assis", 1899); // completo
std::cout << "Livro 1: "; l1.exibir();
std::cout << "Livro 2: "; l2.exibir();
std::cout << "Livro 3: "; l3.exibir();
l3.setAno(1900); // altera o ano
std::cout << "Apos alteracao:\n";
std::cout << "Livro 3: "; l3.exibir();
return 0;
}
Passo a passo
- A classe
Livrotem três membros privados:titulo,autoreano. - O construtor padrão usa lista de inicialização para definir valores padrão.
- O construtor com título e autor também usa lista de inicialização e define
anocomo 0. - O construtor completo usa
this->para atribuir os parâmetros aos membros, pois os nomes coincidem. - O método
setAnoverifica se o novo ano é >= 0 antes de atribuir; caso contrário, mantém o valor atual. - O método
exibirimprime os dados no formato pedido; éconstpois não modifica o objeto. - No
main, criamos três livros com os diferentes construtores e chamamosexibir(). - Alteramos o ano do terceiro livro com
setAno(1900)e exibimos novamente.
Por que funciona
A sobrecarga de construtores permite criar objetos com diferentes níveis de informação. O uso de this-> no construtor completo e no setAno resolve a ambiguidade entre parâmetros e membros. A validação em setAno garante que o estado do objeto permaneça consistente, um princípio do encapsulamento.
Erros comuns
- Não validar em
setAno: aceitar anos negativos quebra a lógica do domínio.
if (ano >= 0) { this->ano = ano; }é essencial. - Esquecer
this->no construtor completo:titulo = titulo;não altera o membro, pois o parâmetro esconde o membro. - Não marcar
exibir()comoconst: impede chamar em objetos constantes e não expressa a intenção de não modificar. - Usar
std::stringsem incluir<string>: erro de compilação. Sempre inclua o cabeçalho necessário.
Outra forma de resolver
Usar argumentos padrão em um único construtor:
Livro(const std::string& titulo = "Desconhecido",
const std::string& autor = "Desconhecido",
int ano = 0) : titulo(titulo), autor(autor), ano(ano) {}
Isso reduz a repetição, mas perde a clareza de ter construtores separados. Prefira a sobrecarga quando os construtores tiverem comportamentos distintos.
Saída esperada
Livro 1: Titulo: Desconhecido, Autor: Desconhecido, Ano: 0
Livro 2: Titulo: 1984, Autor: George Orwell, Ano: 0
Livro 3: Titulo: Dom Casmurro, Autor: Machado de Assis, Ano: 1899
Apos alteracao:
Livro 3: Titulo: Dom Casmurro, Autor: Machado de Assis, Ano: 1900