herança e polimorfismo
………..ficha7, exercicio1 (a19)
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <regex>
#include <initializer_list>
#include <fstream>
using namespace std;
class Imovel
{
float preco;
float area;
string codigo;
static int ordem; //para formar o codigo
//para ser usado por classes derivadas
protected: //nao deixamos o codigo exterior alterar, mas apenas as classes derivadas
void setCodigo(const string& c);
public:
Imovel(float p, float a);
virtual ~Imovel();
float getPreco() const;
void setPreco(const float preco);
float getArea() const;
string getCodigo() const;
static int getOrdem();
virtual string getAsString()const;
};
ostream& operator << (ostream& saida, const Imovel& i); //operador do cout
int Imovel::ordem = 0;
void Imovel::setCodigo(const string& c)
{
codigo = c;
}
Imovel::Imovel(float p, float a):preco(p), area(a)
{
//ou
//ostringstream oss;
//oss << (++ordem);
//codigo = oss.str();
//ou
codigo = to_string(++ordem);
}
Imovel::~Imovel()
{
}
float Imovel::getPreco() const
{
return preco;
}
void Imovel::setPreco(const float preco)
{
this->preco = preco;
}
float Imovel::getArea() const
{
return area;
}
string Imovel::getCodigo() const
{
return codigo;
}
int Imovel::getOrdem()
{
return ordem;
}
string Imovel::getAsString() const
{
ostringstream oss;
oss << " codigo: " << codigo << "\n preco: " << preco << "\n area " << area << endl;
return oss.str();
}
ostream& operator<<(ostream& saida, const Imovel& i)
{
saida << i.getAsString();
return saida;
}
//apartamento deriva de imovel, : public .. e recebe por herança
class Apartamento : public Imovel
{
int numeroAssoalhadas;
int andar;
public:
Apartamento(float area0, int andar0, int numeroAssoalhadas0);
//getAstring é por herança
//precisa de ser redifinida com o override
string getAsString()const override;
};
//o construtor d euma classe derivada já manda executar o construtor da calsse base: Imovel
Apartamento::Apartamento(float area0, int andar0, int numeroAssoalhadas0):Imovel(10* area0, area0), andar(andar0),numeroAssoalhadas(numeroAssoalhadas0)
{
setCodigo("apartamento-" + getAsString());
}
string Apartamento::getAsString() const
{
ostringstream oss;
//preco area -Imovel::getAsString()
oss << "apartamento \n" << Imovel::getAsString() << " andar: " << andar << "\n n. assoalhadas: " << numeroAssoalhadas << endl;
return oss.str();
}
class LojaComercial : public Imovel
{
//nao tem membros privados
public:
LojaComercial(float area);
string getAsString()const override;
};
LojaComercial::LojaComercial(float area):Imovel(15*area, area)
{
setCodigo("lojaComercial-" + getAsString());
}
string LojaComercial::getAsString() const
{
ostringstream oss;
//preco area -Imovel::getAsString()
oss << "lojaComercial \n" << Imovel::getAsString() << " andar: R/C" << endl;
return oss.str();
}
class Imobiliaria
{
//"não deve utilizar uma estrutura de dados para cada tipo diferente de bem imobiliário"
//não usar multiplos vectores, um para cada tipo, mas um para todos
//assim:
vector<Imovel*> imoveis; //coleção de vários tipos de imoveis
//um ponteiro de uma classe derivada pode apontar para a classe base, upcasting
//relação entre imobiliaria e imoveis : agregação
string nome;
int pesquisa(string codigo)const;
public:
Imobiliaria(string nome);
void acrescentaImovel(Imovel* imovel); //recebemos um imovel qualquer
//ponteiro para a base
bool setPreco(string codigo, float preco);
float getPreco(string codigo)const;
bool remover(string codigo);
string getAsString()const;
string getAsString(string codgio0)const;
};
ostream& operator << (ostream& saida, const Imobiliaria& i); //operador do cout
int Imobiliaria::pesquisa(string codigo) const
{
for(unsigned int i = 0; 0 < imoveis.size() ; i++)
{
if(codigo == imoveis[i]->getCodigo())
{
return i;
}
}
return -1;
}
Imobiliaria::Imobiliaria(string nome):nome(nome)
{
}
void Imobiliaria::acrescentaImovel(Imovel* imovel)
{
if(imovel != nullptr)
{
//pode surigr uma loja ou apartamento
imoveis.push_back(imovel);
}
}
bool Imobiliaria::setPreco(string codigo, float preco)
{
if (preco < 0){
return false;
}
int qual = pesquisa(codigo);
if (qual == -1)
{
return false;
}
imoveis[qual]->setPreco(preco);
return true;
}
float Imobiliaria::getPreco(string codigo) const
{
int qual = pesquisa(codigo);
if(qual == -1)
{
return 0;
}
return imoveis[qual]->getPreco();
}
bool Imobiliaria::remover(string codigo)
{
int qual = pesquisa(codigo);
if(qual == -1)
{
return false;
}
//relação de agregação faz-se apenas o erase
imoveis.erase(imoveis.begin() + qual);
return true;
}
string Imobiliaria::getAsString() const
{
ostringstream oss;
oss << "Imobiliaria " << nome << endl;
for(unsigned int i = 0; i < imoveis.size(); i++)
{
oss << imoveis[i]->getAsString() << endl;
}
return oss.str();
}
string Imobiliaria::getAsString(string codgio0) const
{
int qual = pesquisa(codgio0);
if(qual == -1)
{
return "codigo nao existe";
}
return imoveis[qual]->getAsString();
}
ostream& operator<<(ostream& saida, const Imobiliaria& i)
{
saida << i.getAsString();
return saida;
}
//extra Interaccao
class Interaccao {
Imobiliaria* imobiliaria; //classe que envolve toda a lógica
public:
Interaccao(Imobiliaria* imobiliaria0);
int escolheOpcao(vector<string> opcoes);
int lerInt(string msg);
float lerFloat(string msg);
void opcaoAcrescentarApartamento();
void opcaoAcrescentarLoja();
void opcaoPesquisarImovelPorCodigo();
void opcaoPesquisarPrecoDeImovelPorCodigo();
void opcaoActualizarPrecoDeImovelPorCodigo();
void opcaoRemoverImovelPorCodigo();
void corre();
};
Interaccao::Interaccao(Imobiliaria* imobiliaria0) {
imobiliaria = imobiliaria0;
}
int Interaccao::escolheOpcao(vector<string> opcoes) {
for (unsigned int i = 0; i < opcoes.size(); i++)
cout << endl << i << " - " << opcoes[i];
int opcao = -1;
do {
opcao = lerInt("\n\nopcao > ");
} while (opcao < 0 || opcao > opcoes.size());
return opcao;
}
int Interaccao::lerInt(string msg) {
int valor;
bool leu = false;
do {
cout << msg;
string s;
cin >> s;
istringstream iss(s);
if (iss >> valor) // se correu bem a leitura
leu = true;
} while (!leu);
return valor;
}
float Interaccao::lerFloat(string msg) {
float valor;
bool leu = false;
do {
cout << msg;
string s;
cin >> s;
istringstream iss(s);
if (iss >> valor) // se correu bem a leitura
leu = true;
} while (!leu);
return valor;
}
void Interaccao::opcaoAcrescentarApartamento() {
float area;
int andar;
int nAss;
cout << "\nAcrescentar apartamento";
area = lerFloat(" area: ");
andar = lerInt(" andar: ");
nAss = lerInt(" n. de assoalhadas: ");
imobiliaria->acrescentaImovel(new Apartamento(area, andar, nAss));
}
void Interaccao::opcaoAcrescentarLoja() {
float area;
cout << "\nAcrescentar loja: ";
area = lerFloat(" area: ");
imobiliaria->acrescentaImovel(new LojaComercial(area));
}
void Interaccao::opcaoPesquisarImovelPorCodigo() {
string codigo;
cout << "\nPesquisar imovel por codigo\n codigo: ";
cin >> codigo;
cout << imobiliaria->getAsString(codigo) << endl;
}
void Interaccao::opcaoPesquisarPrecoDeImovelPorCodigo() {
string codigo;
cout << "\nPesquisar preco de imovel por codigo\n codigo: ";
cin >> codigo;
cout << imobiliaria->getPreco(codigo) << endl;
}
void Interaccao::opcaoActualizarPrecoDeImovelPorCodigo() {
string codigo;
float preco;
cout << "\nActualizar preco de imovel por codigo\n codigo: ";
cin >> codigo;
cout << imobiliaria->getAsString(codigo) << endl;
preco = lerFloat("\n preco: ");
imobiliaria->setPreco(codigo, preco);
}
void Interaccao::opcaoRemoverImovelPorCodigo() {
string codigo;
cout << "\nRemover imovel por codigo\n codigo: ";
cin >> codigo;
cout << imobiliaria->getAsString(codigo) << endl;
cout << "\n Remover ";
if (imobiliaria->remover(codigo))
cout << " removeu ";
else cout << " nao removeu ";
}
void Interaccao::corre() {
vector<string> opcoes;
opcoes.push_back("Sair");
opcoes.push_back("Listar");
opcoes.push_back("Acrescentar apartamento");
opcoes.push_back("Acrescentar loja");
opcoes.push_back("Pesquisar imovel por codigo");
opcoes.push_back("Pesquisar preco de imovel dado o codigo");
opcoes.push_back("Actualizar o preco de um imovel dado o codigo");
opcoes.push_back("Remover imovel dado o codigo");
int opcao = 0;
do {
opcao = escolheOpcao(opcoes);
switch (opcao) {
case 0: cout << "\nSair\n";
break;
case 1: cout << *imobiliaria << endl;
break;
case 2: opcaoAcrescentarApartamento();
break;
case 3: opcaoAcrescentarLoja();
break;
case 4: opcaoPesquisarImovelPorCodigo();
break;
case 5: opcaoPesquisarPrecoDeImovelPorCodigo();
break;
case 6: opcaoActualizarPrecoDeImovelPorCodigo();
break;
case 7: opcaoRemoverImovelPorCodigo();
break;
}
} while (opcao != 0);
}
int main()
{
Imobiliaria* imobiliaria = new Imobiliaria("Imobiliaria");
Interaccao interaccao(imobiliaria);
interaccao.corre();
delete imobiliaria;
cout << "\nfim do main.." << endl;
return 1;
}
………..ficha7, exercicio3 (a19,a20)
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <regex>
#include <initializer_list>
#include <fstream>
using namespace std;
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <regex>
#include <initializer_list>
#include <fstream>
using namespace std;
/*
+---------------------------------------- + -------------------------- - +
| operador | membro / não membro |
+---------------------------------------- + -------------------------- - +
| todos os operadores unários p.e: ++a, a++ | membro |
| = () -> ->* | têm sempre que ser membro |
| += -= /= *= &= |= %= >>= <<= | membro |
| todos os restantes operadores binários, ==,<<... | globais |
+---
*/
//relação de agregaçao, memoria dinâmica
class Livro
{
string titulo;
string autor;
long isbn;
public:
Livro(const string& titulo0, const string& autor0, const long isbn0);
virtual ~Livro(); //classe de hierarquia, boa pratica
string getTitulo() const;
void setTitulo(const string& titulo);
string getAutor() const;
void setAutor(const string& autor);
long getIsbn() const;
void setIsbn(const long isbn);
virtual string getAsString()const; //para adaptar aos objectos das classes derivadas
virtual Livro* duplica() const;
};
//comparação de dois livros
bool operator==(const Livro& ob1, const Livro& ob2);
// cout objecto-de-livro
ostream& operator<<(ostream& saida, const Livro& lv);
Livro::Livro(const string& titulo0, const string& autor0, const long isbn0):titulo(titulo0), autor(autor0), isbn(isbn0)
{
}
Livro::~Livro()
{
}
string Livro::getTitulo() const
{
return titulo;
}
void Livro::setTitulo(const string& titulo)
{
this->titulo = titulo;
}
string Livro::getAutor() const
{
return autor;
}
void Livro::setAutor(const string& autor)
{
this->autor = autor;
}
long Livro::getIsbn() const
{
return isbn;
}
void Livro::setIsbn(const long isbn)
{
this->isbn = isbn;
}
string Livro::getAsString() const
{
ostringstream oss;
cout << "\ntitulo: " << titulo << " autor: " << autor << " isbn " << isbn << endl;
return oss.str();
}
//criar um clone
Livro* Livro::duplica() const
{
//ou
//return new Livro(*this);
//ou
Livro* lv = new Livro(*this);
return lv;
}
bool operator==(const Livro& ob1, const Livro& ob2)
{
return ob1.getIsbn() == ob2.getIsbn();
}
ostream& operator<<(ostream& saida, const Livro& lv)
{
saida << lv.getAsString();
return saida;
}
class LivroFiccao : public Livro
{
string nomePlaneta;
int anoAccao;
bool realidadeAccao; //0 realista, 1 fatansiosa
public:
LivroFiccao(const string& titulo0, const string& autor0, const long isbn0, const string& nome_planeta, const int ano_accao, const bool realidade_accao);
string getNomePlaneta() const;
int getAnoAccao() const;
bool getRealidadeAccao() const;
string getAsString() const override;
Livro * duplica() const override;
};
LivroFiccao::LivroFiccao(const string& titulo0, const string& autor0, const long isbn0, const string& nome_planeta,
const int ano_accao, const bool realidade_accao) : Livro(titulo0, autor0, isbn0), nomePlaneta(nome_planeta),
anoAccao(ano_accao),realidadeAccao(realidade_accao){
}
string LivroFiccao::getNomePlaneta() const
{
return nomePlaneta;
}
int LivroFiccao::getAnoAccao() const
{
return anoAccao;
}
bool LivroFiccao::getRealidadeAccao() const
{
return realidadeAccao;
}
string LivroFiccao::getAsString() const
{
ostringstream oss;
oss << endl << Livro::getAsString() << " planeta " << nomePlaneta << " ano " << anoAccao << endl;
if(realidadeAccao)
{
oss << " realista \n";
}else
{
oss << " fantasiosa \n";
}
return oss.str();
}
Livro* LivroFiccao::duplica() const
{
return new LivroFiccao(*this);
}
class LivroPolicial: public Livro
{
string nomeDetective;
int numeroTiros;
public:
LivroPolicial(const string& titulo0, const string& autor0, const long isbn0, const string& nomeDetective0, int numeroTiros = 0);
string getNomeDetective() const;
int getNumeroTiros() const;
string getAsString()const override;
Livro* duplica()const override;
};
LivroPolicial::LivroPolicial(const string& titulo0, const string& autor0, const long isbn0,
const string& nomeDetective0, int numeroTiros0):Livro(titulo0, autor0, isbn0),
nomeDetective(nomeDetective0),numeroTiros(numeroTiros0)
{
}
string LivroPolicial::getNomeDetective() const
{
return nomeDetective;
}
int LivroPolicial::getNumeroTiros() const
{
return numeroTiros;
}
string LivroPolicial::getAsString() const
{
ostringstream oss;
oss << endl << Livro::getAsString() << " detective: " << nomeDetective << endl;
if(numeroTiros > 10)
{
oss << " nao aconcelhado a criancas \n";
}else
{
oss << " n. de tiros " << numeroTiros << endl;
}
return oss.str();
}
//nas classes concretas tem que haver um duplica
Livro* LivroPolicial::duplica() const
{
//ou
//return new LivroPolicial(*this);
//ou
LivroPolicial* lvp = new LivroPolicial(*this);
return lvp;
}
//bibliteca tem relação de composição com o livro
//posse exclusiva, implementar: destrutor, construtor por copia, operador atribuição
class Biblioteca
{
string morada;
//qualquer tipo de livros: ponteiros para a classe base, que depois tem acesso às derivadas
vector<Livro *> livros; //vector polimorfico, <Livro *>
int pesquisaLivro(long isbn0) const; //indice, int
public:
Biblioteca(const string& morada);
bool acrescentarLivro(Livro * livro);
bool removerLivro(long isbn0);
//por haver relação de composição, os livros não sobrevivem à destruição da biblioteca
//e destrutor
virtual ~Biblioteca();
//e construtor por copia
Biblioteca(const Biblioteca& ob);
//e operador atribuição
Biblioteca& operator=(const Biblioteca & ob);
string getAsString()const;
};
ostream& operator<<(ostream& saida, const Biblioteca& bibl);
int Biblioteca::pesquisaLivro(long isbn0) const
{
for(unsigned int i=0; i<livros.size(); i++)
{
if(isbn0 == livros[i]->getIsbn())
{
return i;
}
}
return -1;
}
Biblioteca::Biblioteca(const string& morada)
{
}
bool Biblioteca::acrescentarLivro(Livro* livro)
{
if(livro == nullptr || pesquisaLivro(livro->getIsbn())!=-1)
{
return false;
}
Livro* lv = livro->duplica(); //é duplicado com o livro->duplica();, não aceito o que me dão
livros.push_back(lv);
return true;
}
bool Biblioteca::removerLivro(long isbn0)
{
int qual = pesquisaLivro(isbn0);
if(qual == -1)
{
return false;
}
//liberta o obejcto apontado por livro[i]
delete livros[qual]; //só por ser relação de composição
//retirar o vector o pionteito que aponta para memoria já libertada
livros.erase(livros.begin() + qual);
return true;
}
Biblioteca::~Biblioteca()
{
for(Livro * l: livros)
{
delete l;
}
}
Biblioteca::Biblioteca(const Biblioteca& ob)
{
//nao ha ponteiros com valores lixo para limpar
//funcionou o construtor por omissão do vector que criou
//um vector vazio (sem ponteiros)
//e do membro do tipo string
//se houvesse ponteiros com valores lixo punha-se a nullptr
//porque precisamos de preparar o objecto que esta aser criado
//para invocar o operador de atribuição que limpa a memoria velha
//do objecto que o invoca, o primeiro membro da atribuição
*this = ob; //chama o operador atribuicao e copia os dados
//de acordo com o que tem implementado: duplicando
//a memoria dinmica que o destrutor liberta
}
Biblioteca& Biblioteca::operator=(const Biblioteca& ob)
{
//prevenção de auto atribuição
if(this == & ob)
{
return *this;
}
//limpesa da memoria velha do primeiro membro de atribuicao
for(Livro * lv: livros)
{
delete lv;
}
//esvaziar o vector que agora só aponta para memoria ja nao reservada
livros.clear();
//duplicar os objectos dinamicos, copiar a informacao de ob
for(Livro * lv: livros)
{
Livro* p = lv->duplica();
livros.push_back(lv);
}
//e nao esquecer os restantes membros
morada = ob.morada;
return *this;
}
string Biblioteca::getAsString() const
{
ostringstream oss;
oss << "\nmorada: " << morada << endl;
for(unsigned int i=0; i<livros.size(); i++)
{
oss << livros[i]->getAsString();
}
return oss.str();
}
// cout objecto-de-livro
ostream& operator<<(ostream& saida, const Biblioteca & bibl)
{
saida << bibl.getAsString();
return saida;
}
int main()
{
Biblioteca* b = new Biblioteca("aldeia de coimbra");
Livro* p = new LivroPolicial("coimbra", "coimbra", 12345,"coimbra", 1);
b->acrescentarLivro(p);
cout << b->getAsString();
cout << "\nfim do main" << endl;
return 1;
}
………..ficha?, exercicio? (a21), aquario polimorfico
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <regex>
#include <initializer_list>
#include <fstream>
using namespace std;
class Pargo;
class Pescada;
class Aquario;
class Peixe;
//peixe é uma classe abstracta, não se podem criar objectos deste tipo
class Peixe
{
string nomeEspecie;
string cor;
int peso;
int numSerie;
static int sequencia;
//constantes iguais para todos:
static const int INICIAL_PESO = 10;
bool vivo = true; //importante, subs estadio
protected:
void aumentaPeso(int quant0);
public:
Peixe(string nomeEspecie0, string cor0 = "cinzento");
//nao existe aqui construtor default
//assim a classe derivada precisa de um construtor que alimente a classe base
Peixe(const Peixe& orig); //existe porque precisamos que os peixes tenham um num de seq diferente
//tudo é copiado mas o num de série é diferente.
///se fosse o natrual copiaava tudo
int getNumSerie() const;
int getPeso() const;
bool isVivo()const;
virtual string getAsString()const;
//funcao abstracta nao se podem criar objectos desta classe
//pode haver "Peixe *" e "Peixe &"
virtual void alimentar(int quant, Aquario* aquario) = 0;
virtual Peixe* duplica()const = 0;
//serve para criar diferentes tipos de peixes: pargo e pescada
static Peixe* fabrica(string tipo0, string cor0="cinzento");
virtual ~Peixe();
bool setVivo(bool v);
};
ostream& operator<<(ostream& saida, const Peixe& p);
void Peixe::aumentaPeso(int quant0)
{
peso +=quant0;
}
Peixe::Peixe(string nomeEspecie0, string cor0) :nomeEspecie(nomeEspecie0), cor(cor0), peso(INICIAL_PESO), numSerie(sequencia++)
{
}
Peixe::Peixe(const Peixe& orig):nomeEspecie(orig.nomeEspecie), cor(orig.cor), peso(orig.peso), numSerie(sequencia++)
{
//o peixe construido por copia tem outro numero de série
}
int Peixe::getPeso() const
{
return peso;
}
int Peixe::getNumSerie() const
{
return numSerie;
}
bool Peixe::isVivo() const
{
return vivo;
}
Peixe* Peixe::fabrica(string tipo0, string cor0)
{
if(tipo0 == "pargo")
{
return new Pargo(cor0);
}else if(tipo0 == "pescada")
{
return new Pescada;
}
return nullptr;
}
bool Peixe::setVivo(bool v)
{
vivo = v;
}
ostream& operator<<(ostream& saida, const Peixe& p)
{
saida << p.getAsString();
return saida;
}
string Peixe::getAsString() const
{
ostringstream oss;
oss << "\nPeixe: " << nomeEspecie << "\ncor: " << cor << "\npeso: " << peso << "\nnumSerie: " << numSerie << endl;
return oss.str();
}
int Peixe::sequencia = 499; //num. para cada peixe
//NOVO: surgem duas espécies de peixes
class Pargo: public Peixe
{
static const int LIMITE_PESO = 50;
public:
Pargo(string cor0 = "cinzento");
void alimentar(int quant0, Aquario* aquario) override;
Peixe* duplica()const override;
};
Pargo::Pargo(string cor0):Peixe("pargo",cor0)
{
//importante pargo precisa de passar o que o construtor da base precisa, o Peixe
//porque a base não é default
}
void Pargo::alimentar(int quant0, Aquario* aquario)
{
if(quant0<=0 || aquario==nullptr)
{
return;
}
aumentaPeso(quant0);
if(getPeso()>LIMITE_PESO)
{
//aquario->eliminaPeixe(getNumSerie()); //perigo
setVivo(false);
}
}
Peixe* Pargo::duplica() const
{
//duplicação polimórfica
return new Pargo(*this);
}
class Pescada : public Peixe
{
static const int LIMITE_SOLIDAO = 1;
static const int LIMITE_MULTIDAO = 10;
public:
Pescada();
void alimentar(int quant0, Aquario* aquario0) override;
Peixe* duplica()const override;
};
Pescada::Pescada():Peixe("pescada")
{
}
void Pescada::alimentar(int quant0, Aquario* aquario0)
{
if(quant0<=0 || aquario0 == nullptr)
{
return;
}
int num = aquario0->getQuantosPeixes(); //uma estragégia para aceder ao aquario
//ou colocar na classe peixe um ponteiro para aquario
//assim as derivadas teriam sempre acesso
if(num> LIMITE_SOLIDAO && num < LIMITE_MULTIDAO)
{
aumentaPeso(quant0);
}else
{
aumentaPeso(quant0 / 2);
}
}
Peixe* Pescada::duplica() const
{
return new Pescada(*this);
}
//aquario é uma classe abstracta
class Aquario
{
vector<Peixe*> peixes; //vector de ponteiros
int pesquisaPeixe(int numSerie0)const;
void eliminarMortos();
public:
Aquario() = default; //qd criado é um vector vazio
//quando um peixe e posto no aquario, este assume a
//sua posse e controlo total
Aquario(const Aquario& orig); //construtor por cópia
Aquario& operator=(const Aquario& orig); //operador atribuição
virtual ~Aquario();
bool addPeixe(string tipo0, string cor0 = "cinzento");
const Peixe* getPeixe(int numSerie) const;
void alimentar(int quantidade0);
void removePeixe(int numSerie);
bool eliminaPeixe(int numSerie0);
string getAsString()const;
unsigned int getQuantosPeixes()const;
};
void Aquario::alimentar(int quantidade0)
{
//for (Peixe* p : peixes)
//{
// p->alimentar(quantidade0, this); //mt cuidado com isto, usa o vector<Peixe*> novos;
//}
//v2
for(int i = 0; i < peixes.size(); i++)
{
peixes[i]->alimentar(quantidade0, this); //percorrer o vector
}
eliminarMortos(); //vou verificar o boolenao vivo dos peixes
}
string Aquario::getAsString() const
{
ostringstream oss;
oss << "\nAquario; " << endl;
//neste caso vai ser contatenada a informação
//para o objecto que estiver a ser apontado
//não interessa qual
for (Peixe* p : peixes)
{
oss << p->getAsString();
}
return oss.str();
}
unsigned Aquario::getQuantosPeixes() const
{
return peixes.size();
}
bool Aquario::addPeixe(string tipo0, string cor0) {
Peixe* peixe = Peixe::fabrica(tipo0, cor0); //fabrica é static por isso ::
if(peixe==nullptr)
{
return false;
}
peixes.push_back(peixe);
return true;
}
const Peixe* Aquario::getPeixe(int numSerie) const
{
int qual = pesquisaPeixe(numSerie);
if(qual == -1)
{
return nullptr;
}
return peixes[qual];
};
int Aquario::pesquisaPeixe(int numSerie0)const
{
for (int i = 0; i < peixes.size(); i++)
{
if (peixes[i]->getNumSerie() == numSerie0)
{
return i;
}
}
return -1;
}
void Aquario::eliminarMortos()
{
//formula
//ou
//for(vector<Peixe*>::iterator it = peixes.begin() ; it != peixes.end(); )
//ou
for (auto it = peixes.begin(); it != peixes.end();)
{
if (!(*it)->isVivo())
{
delete (*it);
it = peixes.erase(it);
}
else
{
++it;
}
}
}
Aquario::~Aquario()
{
for (Peixe* p : peixes)
{
delete p;
}
cout << "\n~Aquario()" << endl;
}
Aquario::Aquario(const Aquario& orig)
{
//funcionou o constru por defeito do vector
//o vector está vazio
//não há ponteiros com lixo
*this = orig;
}
Aquario& Aquario::operator=(const Aquario& orig)
{
//prevenção da auto atribuição
if (this == &orig)
{
return *this;
}
//libtertar mem dina velha
for (Peixe* p : peixes)
{
delete p;
}
//esvaziar o vector
peixes.clear();
//copiar a informacao de orig, duplicando os objectos dinamicos
for (Peixe * peixe : orig.peixes) {
Peixe * p = peixe->duplica();
peixes.push_back(p);
}
return *this;
}
void Aquario::removePeixe(int numSerie)
{
int qual = pesquisaPeixe(numSerie);
if (qual == -1)
{
return;
}
delete peixes[qual];
peixes.erase(peixes.begin() + qual);
}
bool Aquario::eliminaPeixe(int numSerie0)
{
int qual = pesquisaPeixe(numSerie0);
if(qual == -1)
{
return false;
}
//remove o peixe do aquario, é destruido
delete peixes[qual];
//depois de feito o dele (libertada a memoria)
//precisamos de retirar do vector
//o ponteio para memoria ja nao reservada
peixes.erase(peixes.begin() + qual);
return true;
}
int main()
{
cout << "\nfim do main" << endl;
return 1;
}
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
class Caderno
{
private:
//membros variáveis
string marca;
string cor;
int numFolhas;
string tamanho;
public:
Caderno(const string& marca, const string& cor, const int num_folhas, const string& tamanho)
//const não consigo alterar o argumento que vem da main, assim fica mais eficiente/seguro,
//e tambem assim posso fazer uso de uma const, usando por exemplo "marca"
//o int pode ter const ou não e referencia, e porque é uma coisa pequena
: marca(marca),
cor(cor),
numFolhas(num_folhas),
tamanho(tamanho)
{
}
//membros funções
//funções get
//os consts sigificam que não podem alterar nada, é uma função de consulta
string getMarca() const
{
return marca;
}
string getCor() const
{
return cor;
}
int getNumfolhas() const
{
return numFolhas;
}
string getTamanho() const
{
return tamanho;
}
//funções set
void setMarca(const string & marca)
{
this->marca = marca;
}
void setCor(const string & cor)
{
this->cor = cor;
}
void setNumfolhas(int num_folhas)
{
if(num_folhas>0){
numFolhas = num_folhas;
}else
{
numFolhas = 0;
}
}
void setTamanho(const string& tamanho)
{
this->tamanho = tamanho;
}
string getAsString()const;
};
string Caderno::getAsString()const
{
ostringstream oss;
oss << "\nmarca: " << marca
<< "\ncor: " << cor
<< "\nnum folhas: " << numFolhas
<< "n\ntamanho: " << tamanho;
return oss.str();
}
int main()
{
const Caderno Cad1("bic","branca",2,"a4"); //const não posso alterar
cout << Cad1.getAsString();
cout << "\nfim do main" << endl;
return 0;
}
………..ficha?, exercicio? (a21, a22), aquario polimorfico v2
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <regex>
#include <initializer_list>
#include <fstream>
using namespace std;
class Aquario;
class Pargo;
class Pescada;
//peixe é uma classe abstracta, não se podem criar objectos deste tipo
class Peixe
{
string nomeEspecie;
string cor;
int peso;
int numSerie;
static int sequencia;
//constantes iguais para todos:
static const int INICIAL_PESO = 10;
bool vivo = true; //importante, subs estadio
//v2
Aquario* aquario = nullptr;
protected:
void aumentaPeso(int quant0);
Aquario* getAquario(); //v2
public:
Peixe(Aquario* aq0, string nomeEspecie0, string cor0 = "cinzento"); //v2
//nao existe aqui construtor default
//assim a classe derivada precisa de um construtor que alimente a classe base
Peixe(const Peixe& orig); //existe porque precisamos que os peixes tenham um num de seq diferente
//tudo é copiado mas o num de série é diferente.
///se fosse o natrual copiaava tudo
int getNumSerie() const;
int getPeso() const;
bool isVivo()const;
virtual string getAsString()const;
//funcao abstracta nao se podem criar objectos desta classe
//pode haver "Peixe *" e "Peixe &"
//virtual void alimentar(int quant, Aquario* aquario) = 0;
virtual void alimentar(int quant) = 0; //v2
virtual Peixe* duplica()const = 0;
//serve para criar diferentes tipos de peixes: pargo e pescada
static Peixe* fabrica(string tipo0, Aquario * aq0, string cor0="cinzento");
virtual ~Peixe();
bool setVivo(bool v);
//v3
void setAquario(Aquario* aqua0);
};
ostream& operator<<(ostream& saida, const Peixe& p);
void Peixe::aumentaPeso(int quant0)
{
peso +=quant0;
}
Aquario* Peixe::getAquario()
{
return aquario;
}
Peixe::Peixe(Aquario * aq0, string nomeEspecie0, string cor0) :aquario(aq0),nomeEspecie(nomeEspecie0), cor(cor0), peso(INICIAL_PESO), numSerie(sequencia++)
{
}
Peixe::Peixe(const Peixe& orig):nomeEspecie(orig.nomeEspecie), cor(orig.cor), peso(orig.peso), numSerie(sequencia++)
{
//o peixe construido por copia tem outro numero de série
}
int Peixe::getPeso() const
{
return peso;
}
int Peixe::getNumSerie() const
{
return numSerie;
}
bool Peixe::isVivo() const
{
return vivo;
}
Peixe* Peixe::fabrica(string tipo0, Aquario * aqu0, string cor0)
{
if(tipo0 == "pargo")
{
return new Pargo(aqu0, cor0);
}else if(tipo0 == "pescada")
{
return new Pescada(aqu0);
}
return nullptr;
}
bool Peixe::setVivo(bool v)
{
vivo = v;
}
void Peixe::setAquario(Aquario* aqua0)
{
this->aquario = aqua0;
}
ostream& operator<<(ostream& saida, const Peixe& p)
{
saida << p.getAsString();
return saida;
}
string Peixe::getAsString() const
{
ostringstream oss;
oss << "\nPeixe: " << nomeEspecie << "\ncor: " << cor << "\npeso: " << peso << "\nnumSerie: " << numSerie << endl;
return oss.str();
}
int Peixe::sequencia = 499; //num. para cada peixe
//NOVO: surgem duas espécies de peixes
class Pargo: public Peixe
{
static const int LIMITE_PESO = 50;
public:
Pargo(Aquario * aqua0, string cor0 = "cinzento");
void alimentar(int quant0) override;
Peixe* duplica()const override;
};
Pargo::Pargo(Aquario* aqua0, string cor0):Peixe(aqua0, "pargo",cor0)
{
//importante pargo precisa de passar o que o construtor da base precisa, o Peixe
//porque a base não é default
}
void Pargo::alimentar(int quant0)
{
if(quant0<=0 || getAquario()==nullptr)
{
return;
}
aumentaPeso(quant0);
if(getPeso()>LIMITE_PESO)
{
//aquario->eliminaPeixe(getNumSerie()); //perigo
setVivo(false);
}
}
Peixe* Pargo::duplica() const
{
//duplicação polimórfica
return new Pargo(*this);
}
class Pescada : public Peixe
{
static const int LIMITE_SOLIDAO = 1;
static const int LIMITE_MULTIDAO = 10;
public:
Pescada(Aquario * aqu0);
void alimentar(int quant0) override;
Peixe* duplica()const override;
};
Pescada::Pescada(Aquario* aqu0):Peixe(aqu0, "pescada")
{
}
void Pescada::alimentar(int quant0)
{
if(quant0<=0 || getAquario() == nullptr) //v2
{
return;
}
int num = getAquario()->getQuantosPeixes(); //uma estragégia para aceder ao aquario, v2
//ou colocar na classe peixe um ponteiro para aquario
//assim as derivadas teriam sempre acesso
if(num> LIMITE_SOLIDAO && num < LIMITE_MULTIDAO)
{
aumentaPeso(quant0);
}else
{
aumentaPeso(quant0 / 2);
}
}
Peixe* Pescada::duplica() const
{
return new Pescada(*this);
}
//aquario é uma classe abstracta
class Aquario
{
vector<Peixe*> peixes; //vector de ponteiros
int pesquisaPeixe(int numSerie0)const;
void eliminarMortos();
public:
Aquario() = default; //qd criado é um vector vazio
//quando um peixe e posto no aquario, este assume a
//sua posse e controlo total
Aquario(const Aquario& orig); //construtor por cópia
Aquario& operator=(const Aquario& orig); //operador atribuição
virtual ~Aquario();
bool addPeixe(string tipo0, string cor0 = "cinzento");
const Peixe* getPeixe(int numSerie) const;
void alimentar(int quantidade0);
void removePeixe(int numSerie);
bool eliminaPeixe(int numSerie0);
string getAsString()const;
unsigned int getQuantosPeixes()const;
};
void Aquario::alimentar(int quantidade0)
{
//for (Peixe* p : peixes)
//{
// p->alimentar(quantidade0, this); //mt cuidado com isto, usa o vector<Peixe*> novos;
//}
//v2
for(int i = 0; i < peixes.size(); i++)
{
peixes[i]->alimentar(quantidade0); //percorrer o vector, v2
}
eliminarMortos(); //vou verificar o boolenao vivo dos peixes
}
string Aquario::getAsString() const
{
ostringstream oss;
oss << "\nAquario; " << endl;
//neste caso vai ser contatenada a informação
//para o objecto que estiver a ser apontado
//não interessa qual
for (Peixe* p : peixes)
{
oss << p->getAsString();
}
return oss.str();
}
unsigned Aquario::getQuantosPeixes() const
{
return peixes.size();
}
bool Aquario::addPeixe(string tipo0, string cor0) {
Peixe* peixe = Peixe::fabrica(tipo0, this, cor0); //fabrica é static por isso ::, v2
if(peixe==nullptr)
{
return false;
}
peixes.push_back(peixe);
return true;
}
const Peixe* Aquario::getPeixe(int numSerie) const
{
int qual = pesquisaPeixe(numSerie);
if(qual == -1)
{
return nullptr;
}
return peixes[qual];
};
int Aquario::pesquisaPeixe(int numSerie0)const
{
for (int i = 0; i < peixes.size(); i++)
{
if (peixes[i]->getNumSerie() == numSerie0)
{
return i;
}
}
return -1;
}
void Aquario::eliminarMortos()
{
//formula
//ou
//for(vector<Peixe*>::iterator it = peixes.begin() ; it != peixes.end(); )
//ou
for (auto it = peixes.begin(); it != peixes.end();)
{
if (!(*it)->isVivo())
{
delete (*it);
it = peixes.erase(it);
}
else
{
++it;
}
}
}
Aquario::~Aquario()
{
for (Peixe* p : peixes)
{
delete p;
}
cout << "\n~Aquario()" << endl;
}
Aquario::Aquario(const Aquario& orig)
{
//funcionou o constru por defeito do vector
//o vector está vazio
//não há ponteiros com lixo
*this = orig;
}
Aquario& Aquario::operator=(const Aquario& orig)
{
//prevenção da auto atribuição
if (this == &orig)
{
return *this;
}
//libtertar mem dina velha
for (Peixe* p : peixes)
{
delete p;
}
//esvaziar o vector
peixes.clear();
//copiar a informacao de orig, duplicando os objectos dinamicos
for (Peixe * peixe : orig.peixes) {
Peixe * p = peixe->duplica();
p->setAquario(this); //para aponter para o aquario novo, v3
peixes.push_back(p);
}
return *this;
}
void Aquario::removePeixe(int numSerie)
{
int qual = pesquisaPeixe(numSerie);
if (qual == -1)
{
return;
}
delete peixes[qual];
peixes.erase(peixes.begin() + qual);
}
bool Aquario::eliminaPeixe(int numSerie0)
{
int qual = pesquisaPeixe(numSerie0);
if(qual == -1)
{
return false;
}
//remove o peixe do aquario, é destruido
delete peixes[qual];
//depois de feito o dele (libertada a memoria)
//precisamos de retirar do vector
//o ponteio para memoria ja nao reservada
peixes.erase(peixes.begin() + qual);
return true;
}
int main()
{
Aquario* aq1 = new Aquario;
aq1->addPeixe("pescada");
aq1->addPeixe("pargo", "laranja");
cout << aq1->getAsString() << endl;
Aquario* aq2 = new Aquario;
aq2->addPeixe("pargo", "azul");
cout << aq2->getAsString() << endl;
*aq2 = *aq1;
cout << aq2->getAsString() << endl;
aq2->alimentar(10);
cout << aq2->getAsString() << endl;
cout << "\nfim do main" << endl;
return 1;
}
………..ficha7, exercicio4 (a22, a23) exercicio global
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <regex>
#include <initializer_list>
#include <fstream>
class Ginasio;
using namespace std;
class Tarifario
{
//sem usar contentores da STL
//(vector, lista, maps.. )
//e implica: memoria dinamica, destrutor, operador atribuição, construtor por cópia
//deve ser usado um array dinamico de inteiros
unsigned int* treinos; //ponteiro para o array dinamico
unsigned int quantos; //quantidade de elementos, pois não podemos usar o size(), serve para controlar qts
//vai ser implementada pelas derivadas
//esta função apenas se destina a calcular o pagamento
//a função calculaPagamentoEApagaTreinos invoca esta e apaga os treinos
virtual unsigned int calculaPagamento()const = 0; //abstracta
public:
void acrescentaTreino(unsigned int at);
unsigned int calculaPagamentoEApagaTreinos();
//é preciso o construtor para inicializar o ponteiro e a variavel quantos
Tarifario(); //este é um construtor por omissão
//vai ser preciso ter o destrutor para devolver a memoria ocupada pela matriz dinamica
virtual ~Tarifario(); //existem derivas esta é virtual
//justificação de:
//a matriz dinamica de inteiros(treinos) pertence exclusivamente a cada objeto
//de tarifario mas nao e automaticamente copiada quando se copiam ou atribuem estes
//objectos (apenas o ponteiro e copiado lvando a partilha de matriz entre objectos
//e mais tarde a deletes repetidos da mesma matriz, entre outras incoerencias)
// => é preciso fazer o operador de atribuição e o construtor por cópia
Tarifario(const Tarifario& orig);
Tarifario& operator=(const Tarifario& orig);
unsigned int getNumTreinos()const;
unsigned int getTreino(unsigned int i)const;
virtual string getAsString() const;
//tem que ser abstracta tb. nao se pode construir
//um tarifario ainda porque é classe abstracta
virtual Tarifario* duplica()const = 0; //duplicação polimorfica, por causa do operador atribuição do cliente
};
void Tarifario::acrescentaTreino(unsigned at)
{
//ao inves do push back
unsigned int* aux = new unsigned int[quantos + 1];
for(unsigned int i=0; i< quantos; i++)
{
aux[i] = treinos[i];
}
aux[quantos] = at;
quantos++;
delete[] treinos;
treinos = aux;
}
unsigned Tarifario::calculaPagamentoEApagaTreinos()
{
//vai chamar a função correspondente a classe do objeto que invoca
unsigned int conta = calculaPagamento(); //definido nas classes concretas calculaPagamento();
delete[] treinos;
treinos = nullptr;
quantos = 0;
return conta;
}
Tarifario::Tarifario()
{
treinos = nullptr; //inicialmente nao existem treinos
quantos = 0;
}
Tarifario::~Tarifario()
{
delete[] treinos; //libertar a memoria dinamica
}
Tarifario::Tarifario(const Tarifario& orig)
{
//pre inicialização para que o operador de atribuição
//consiga trabalhar bem ( precisa de ter o objecto num estado
//coerente dai a inicialização previa
//para acontecer o delete apenas a um valor de um ponteiro
//nulo ou com um valor dado por new
treinos = nullptr; //treinos é um vector ponteiro que nasce com lixo, por isso é impts isto!
quantos = 0;
//usar o operador de atribuição
*this = orig;
}
Tarifario& Tarifario::operator=(const Tarifario& orig) //a= b
{
//testa auto-aribuição para evitar trabalho desnecssário e possivel incorencia
//e libertação dos treinos da orgem da copia (que coincide com o destino)
//na memoria diamica se nao o mesmo -> ja sao iguaos = concluido
if(this == &orig)
{
return *this;
}
//devolve os recursos ocupados pelo objecto alvo da atribuição
delete[] treinos; //treinos é um vector ponteiro que nasce com lixo
treinos = nullptr;
quantos = 0;
//se o outro objecto tambem tem 0 treinos ja estamos iguais. concluido.
if(orig.treinos == nullptr)
{
return * this;
}
//senão:
//criar recursos iguais (copiar) aos do outro objecto
//alocar matriz dnamica para tantos treinos como os do outro objecto
//copiar dos dados: o conteudo da matriz e restantes membros
treinos = new unsigned int[orig.quantos];
quantos = orig.quantos;
for(unsigned int i = 0 ; i < quantos; i++)
{
treinos[i] = orig.treinos[i]; //copiar todos
}
return *this;
}
unsigned Tarifario::getNumTreinos() const
{
return quantos;
}
unsigned Tarifario::getTreino(unsigned i) const
{
if(i<= 0|| (i>=quantos))
{
return 0;
}
return treinos[i];
}
string Tarifario::getAsString() const
{
ostringstream oss;
oss << " tarifario: " << endl;
return oss.str();
}
//relação com tarifario é de composição, sento Apressado uma sub-classe
//apressado é uma classe derivada concreta e tem que existir:
//tem que se concretirar tdoas as funções abstractas
//tem que haver um construtor que alimenta a classe base, se tiver argumentos o construtor da base
//mas neste caso é um construtor por omissão
class Apressado :public Tarifario
{
unsigned int calculaPagamento() const override; //é abstracta na classe tarifario (virtual)
public:
Tarifario * duplica() const override; //é abstracta na classe tarifario (virtual)
string getAsString() const override;
};
unsigned Apressado::calculaPagamento() const
{
unsigned int custo = 0;
unsigned int numTreinos = getNumTreinos();
for(unsigned int i = 0 ; i< numTreinos; i++)
{
unsigned int treino = getTreino(i);
if(treino <=10)
{
custo += 10;
}else if(treino > 10 && treino < 20)
{
custo += 15;
}else
{
custo += 25;
}
}
return custo;
}
Tarifario* Apressado::duplica() const
{
return new Apressado(*this);
}
string Apressado::getAsString() const
{
ostringstream oss;
oss << " apressado " << endl;
return oss.str();
}
//cliente genérico, significa que é uma classe base de uma hierarquia
class Cliente
{
string nome;
unsigned int bi; //ou string
Tarifario* tarifario; //aponta para um qualquer tipo de tarifario que exista
int horarioInicio;
//para impedir a copia e a atribuição de objectos
//se for solicitado era:
//Cliente(const Cliente& cli) = delete;
//Cliente& operator=(const Cliente& cli) = delete;
public:
//nao podem existir clientes sem tarifario, é necessário o construtor
Cliente(const string& nome, unsigned long bi, Tarifario* const tarifario);
//destrutor para apagar tarifario
virtual ~Cliente();
void iniciaTreino(int hora);
void terminaTreino(int hora);
unsigned int paga();
//pergunta exame
//um método generico que não pode ser já implementado, é uma função abstracta, virtual e =0
//e vao ter codigo nas classes derivadas
virtual void reageEntrada(Ginasio* g) = 0;
virtual void reageSaida(Ginasio* g) = 0;
void mudaTarifario(Tarifario* tarifario);
unsigned int getBi()const;
bool estarATreinar()const;
//a c.5)
Cliente(const Cliente& cli);
Cliente& operator=(const Cliente& cli);
virtual string getAsString()const;
//tem que ser virtual pura (cliente é abstracta)
virtual Cliente* duplica()const = 0;
};
Cliente::Cliente(const string& nome, unsigned long bi, Tarifario* const tarifario) : nome(nome), bi(bi), tarifario(tarifario)
{
horarioInicio = -1; //nao esta a treinar quando é criado
}
Cliente::~Cliente()
{
delete tarifario;
cout << "~Cliente" << endl;
}
void Cliente::iniciaTreino(int hora)
{
if(horarioInicio==-1)
{
horarioInicio = hora;
}
}
void Cliente::terminaTreino(int hora)
{
if(horarioInicio != -1)
{
tarifario->acrescentaTreino(hora - horarioInicio);
horarioInicio = -1;
}
}
unsigned Cliente::paga()
{
//quem calcula é o tarifario, e o cliente tem
return tarifario->calculaPagamentoEApagaTreinos();
}
void Cliente::mudaTarifario(Tarifario* tarifario)
{
if(this->tarifario != nullptr)
{
//so muda se o novo tarifario existir mesmo
//apaga tarifario anterior (deixa de servir)
//(obs: os treinos do antigo tarifario ficaram
//por pagar deixa-se pagar antes de mudar de tarifario
delete this->tarifario;
this->tarifario = tarifario;
}
}
bool Cliente::estarATreinar() const
{
return horarioInicio != -1;
}
Cliente::Cliente(const Cliente& cli)
{
//efectua pre inicilização para compatibilizar com o operador
//neste caso basta colocar o ponteiro tarifario num estacio inciial coerente
tarifario = nullptr;
//usa operador atribuicao
*this = cli;
}
Cliente& Cliente::operator=(const Cliente& cli)
{
//testa a auto atribuição para evitar trabalho desnecessario
//e libertacao do tarifario da origem da copia (que coincide com o destino)
if(this == &cli)
{
return *this;
}
//liberta recursos atuais do objecto da atribuicao
//neste caso so o objeto tarifario
delete tarifario;
//cria/copia recursos (iguais ao) do outro objeto
//no caso do tarifario, pode ser de qualquer tipo
//usar o new nao e viavel ( nao se sabe o tipo )
//o tarifario que se duplique
//tem que ser pela via do "duplica" (implementar no tarifario e derivadas)
nome = cli.nome;
bi = cli.bi;
horarioInicio = cli.horarioInicio;
tarifario = cli.tarifario->duplica();
return *this;
}
string Cliente::getAsString() const
{
ostringstream oss;
oss << nome << " - bi: " << bi;
return oss.str();
}
//classe concreta
//e)
class Sociavel: public Cliente
{
public:
Sociavel(const string& nome, const unsigned long bi, Tarifario* const tarifario);
void reageEntrada(Ginasio* g) override;
void reageSaida(Ginasio* g) override;
Cliente* duplica() const override;
string getAsString() const override;
};
Sociavel::Sociavel(const string& nome, const unsigned long bi, Tarifario* const tarifario) : Cliente(nome, bi, tarifario)
{
}
void Sociavel::reageEntrada(Ginasio* g)
{
//nao faz nada
}
void Sociavel::reageSaida(Ginasio* g)
{
if(g->getNumClientesATreinar()==1) //se for só ele
{
g->saiClienteDoTreino(getBi());
}
}
Cliente* Sociavel::duplica() const
{
return new Sociavel(*this);
}
string Sociavel::getAsString() const
{
ostringstream oss;
oss << "sociavel - " << Cliente::getAsString();
return oss.str();
}
//os clientes pertencem ao ginasio
//qd se destroi o ginasio o cliente tambem serão
class Ginasio
{
//clientes de diversos tipos
//vector de ponteiros para a classe base
//* para validar o polimorfismo
vector<Cliente*> clientes;
unsigned int relogio;
unsigned int pesquisaClienteDadoBi(unsigned int bi);
public:
void avancaRelogio(int tempo);
bool acrescentaCliente(Cliente* c);
unsigned int paga(unsigned int bi);
void entraClienteNoTreino(unsigned int bi);
void saiClienteDoTreino(unsigned int bi);
void removeCliente(unsigned int bi);
Ginasio();
~Ginasio();
unsigned int getNumClientesATreinar()const;
bool saiClienteDoTreino(int s);
Ginasio& operator=(const Ginasio& orig);
Ginasio(const Ginasio& orig);
string getAsString() const;
};
unsigned Ginasio::pesquisaClienteDadoBi(unsigned bi)
{
for(unsigned int i = 0; i<clientes.size(); i++)
{
if(bi == clientes[i]->getBi())
{
return i;
}
}
return -1;
}
void Ginasio::avancaRelogio(int tempo)
{
relogio += tempo;
}
bool Ginasio::acrescentaCliente(Cliente* c)
{
if(c == nullptr)
{
return false;
}
//se existem clientes com o mesmo bi
if(pesquisaClienteDadoBi(c->getBi()) != -1)
{
return false;
}
clientes.push_back(c->duplica());
return true;
}
unsigned Ginasio::paga(unsigned bi)
{
//procura cliente. sera devolvida a posicao no vector
unsigned int indice = pesquisaClienteDadoBi(bi);
if(indice != -1)
{
//se encontrou..
return clientes[indice]->paga();
}
return 0;
}
void Ginasio::entraClienteNoTreino(unsigned bi)
{
unsigned int indice = pesquisaClienteDadoBi(bi);
if(indice == -1)
{
return;
}
//verificar se o cliente ainda não estava a treinar
if(clientes[indice]->estarATreinar() == true)
{
return;
}
//avisa os outros clientes a treinar que entrou na sala
for(unsigned int i=0; i< clientes.size(); i++)
{
if(clientes[i]->estarATreinar()){
clientes[i]->reageEntrada(this);
}
}
//o cliente inicia o treino
clientes[indice]->iniciaTreino(relogio);
}
void Ginasio::saiClienteDoTreino(unsigned bi)
{
unsigned int indice = pesquisaClienteDadoBi(bi);
if(indice == -1)
{
return;
}
//cliente pode nao estar a treinar
if(clientes[indice]->estarATreinar() == false)
{
return;
}
//primeiro tira da sala de treino e so depois avisa os que ficaram que saiu um
clientes[indice]->terminaTreino(relogio);
//avisa os outros clientes a treinar que saiu um da sala
for(unsigned int i = 0; i< clientes.size(); i++)
{
if(clientes[i]->estarATreinar())
{
clientes[i]->reageSaida(this);
}
}
}
void Ginasio::removeCliente(unsigned bi)
{
//procura o cliente na base de dados de clientes
unsigned int indice = pesquisaClienteDadoBi(bi);
if(indice == -1)
{
return;
}
//encontrou manda sair do treino
saiClienteDoTreino(bi);
//antes de ir embora pagar a conta
clientes[indice]->paga();
//apaga, os clientes pertencem ao ginasio
delete clientes[indice];
//retira do vector o ponteiro para memoria já libertada
clientes.erase(clientes.begin() + indice);
}
Ginasio::Ginasio():relogio(0)
{
}
Ginasio::~Ginasio()
{
//apaga as fichas
for(unsigned int i = 0; i< clientes.size(); i++)
{
delete clientes[i]; //os clientes pertencem ao ginasio
}
}
unsigned Ginasio::getNumClientesATreinar() const
{
unsigned int n = 0;
for(unsigned int i = 0; i<clientes.size();i++)
{
if(clientes[i]->estarATreinar())
{
n++;
}
}
return n;
}
Ginasio& Ginasio::operator=(const Ginasio& orig)
{
//testar a auto atribuição se sao o mesmo objecto, "ja nao sao iguais"
//nao se libertam recursos dos destino da atribuição porque coincide com a origem
if(this == &orig)
{
return *this;
}
//apaga o conceudo ja existente no "alvo" da atribuicao (*this)
for(unsigned int i = 0; i< clientes.size(); i++)
{
delete clientes[i]; //apaga mesmo os clientes (eram do ginasio)
}
//os clientes foram apagados, mas os ponteiros
clientes.clear(); //ainda estão no vector, o qual deve ser esvaziado
for(unsigned int i = 0; i<clientes.size(); i++)
{
//independentemente do tipo do cliente, duplica
clientes.push_back(orig.clientes[i]->duplica());
}
//copiar o valor do relgio
relogio = orig.relogio;
return *this;
}
Ginasio::Ginasio(const Ginasio& orig)
{
//nao é preciso pre inicialização explicita porque o vector e
//inicializado automaticamente com o seu construtor por omissao
//um avez que nao foi usado nenhum outro na lista de inicializaca deste construtor
//e que o deixa vazio e pronto a usar. noutros casos poderia ser necessario algo aqui
*this = orig;
}
string Ginasio::getAsString() const
{
ostringstream oss;
oss << "\n ginasio" << "(tempo " << relogio << ")" << "clientes: " << endl;
for(unsigned int i = 0 ; i < clientes.size(); i++)
{
oss << clientes[i]->getAsString() << endl;
}
oss << "\na treinar " << endl;
for(unsigned int i = 0; i< clientes.size(); i++)
{
if(clientes[i]->estarATreinar())
{
oss << clientes[i]->getAsString() << endl;
}
}
return oss.str();
}
int main()
{
cout << "\nfim do main" << endl;
return 1;
}
}
………..ficha7, exercicio5 (a24)
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <regex>
#include <initializer_list>
#include <fstream>
using namespace std;
class Tagarela;
class FalaPouco;
//classe base, abstracta, relação de
class Tarifario
{
//nao existem dados, quem tem é o Cartao
//nao tem informação
public:
//só tem funções
Tarifario() = default;
virtual float calculaCustoChamada(int s) const = 0; //virtual e =0
virtual float fazCarregamento(float quantia) const = 0;
virtual bool autorizaChamada(int saldo) const = 0;
virtual string getNome()const = 0;
virtual Tarifario* duplica() const = 0; //por causa do operador atribuição na classe rede
static Tarifario* fabrica(string tipo); //fabrica de tarifarios, para os arrumar
virtual string getAsString() const;
};
Tarifario* Tarifario::fabrica(string tipo)
{
if(tipo=="Tagarela")
{
return new Tagarela;
}else if(tipo == "FalaPouco")
{
return new FalaPouco;
}else
{
return nullptr;
}
}
string Tarifario::getAsString() const
{
ostringstream oss;
oss << "tarifario: " << endl;
return oss.str();
}
//classe derivada
class Tagarela : public Tarifario
{
//existem constantes desta classe
static const float PRIMEIRO_MINUTO;
static const float MINUTOS_SEGUINTES;
static const float BONUS;
static const float BASE;
public:
float calculaCustoChamada(int s) const override;
float fazCarregamento(float quantia) const override;
bool autorizaChamada(int saldo) const override;
string getNome() const override;
Tarifario* duplica() const override;
string getAsString() const override;
};
//concretizar as constantes
const float Tagarela::PRIMEIRO_MINUTO = 0.02f;
const float Tagarela::BONUS = 5.0f;
const float Tagarela::BASE = 25.0f;
const float Tagarela::MINUTOS_SEGUINTES = 0.02f;
float Tagarela::calculaCustoChamada(int s) const
{
if(s<=0) //saldo
{
return 0;
}
float aux_custo = PRIMEIRO_MINUTO;
if(s>60)
{
aux_custo += MINUTOS_SEGUINTES * (s - 60) / 60.0;
}
return aux_custo;
}
float Tagarela::fazCarregamento(float quantia) const
{
if(quantia<BASE)
{
return 0;
}else if(quantia>=2*BASE)
{
quantia += BONUS;
}
return quantia;
}
bool Tagarela::autorizaChamada(int saldo) const
{
return saldo >= -PRIMEIRO_MINUTO;
}
string Tagarela::getNome() const
{
return "Tagarela";
}
Tarifario* Tagarela::duplica() const
{
return new Tagarela(*this);
}
string Tagarela::getAsString() const
{
ostringstream oss;
oss << "tagarela: " << endl;
return oss.str();
}
//classe derivada
class FalaPouco : public Tarifario
{
static const float TODOS_MINUTOS;
static const float CARREGAMENTOS;
static const float BONUS_CARREGAMENTOS;
public:
float calculaCustoChamada(int s) const override;
float fazCarregamento(float quantia) const override;
bool autorizaChamada(int saldo) const override;
string getNome() const override;
Tarifario* duplica() const override;
string getAsString() const override;
};
//concretizar as constantes
const float FalaPouco::TODOS_MINUTOS = 0.25f;
const float FalaPouco::CARREGAMENTOS = 10.0f;
const float FalaPouco::BONUS_CARREGAMENTOS = 0.2f;
float FalaPouco::calculaCustoChamada(int s) const
{
if(s<0)
{
return 0;
}
return TODOS_MINUTOS * s / 60.0;
}
float FalaPouco::fazCarregamento(float quantia) const
{
if(quantia<CARREGAMENTOS)
{
return 0;
}
int n = rand() % 10; //de 0 a 9
if(n<2) //<2 é 20%
{
quantia *= 2;
}
return quantia;
}
bool FalaPouco::autorizaChamada(int saldo) const
{
//ou talvez meu
if(saldo<=(TODOS_MINUTOS*10))
{
return false;
}
return true;
//ou
//return saldo >= - TODOS_MINUTOS * 10;
}
string FalaPouco::getNome() const
{
return "FalaPouco";
}
Tarifario* FalaPouco::duplica() const
{
return new FalaPouco(*this);
}
string FalaPouco::getAsString() const
{
ostringstream oss;
oss << "falapouco" << endl;
return oss.str();
}
class Cartao
{
long numero;
float saldo;
Tarifario* tarifario;
public:
Cartao(const long numero, Tarifario* const tarifario);
virtual ~Cartao();
long getNumero() const;
float getSaldo() const;
string getNomeTarifario() const;
void setTarifario(Tarifario* const tarifario0);
bool autorizaChamada()const;
void registaChamada(int saldo);
bool fazCarregamento(float quantia);
string getAsString()const;
};
bool operator==(const Cartao& orig1, const Cartao& orig2); //para dois tarifários iguais!!
Cartao::Cartao(const long numero0, Tarifario* const tarifario0):numero(numero0), tarifario(tarifario0), saldo(0){}
long Cartao::getNumero() const
{
return numero;
}
float Cartao::getSaldo() const
{
return saldo;
}
string Cartao::getNomeTarifario() const
{
return tarifario->getNome();
}
void Cartao::setTarifario(Tarifario* const tarifario0)
{
this->tarifario = tarifario0;
}
bool Cartao::autorizaChamada() const
{
//função polimorfica, conforme o tarifario
return tarifario->autorizaChamada(saldo);
}
void Cartao::registaChamada(int saldo0)
{
//função polimorfica, conforme o tarifario
float aux_custo = tarifario->calculaCustoChamada(saldo0);
saldo = -aux_custo;
}
bool Cartao::fazCarregamento(float quantia0)
{
//função polimorfica, conforme o tarifario
float aux_carregamento = tarifario->fazCarregamento(quantia0);
saldo += aux_carregamento;
return aux_carregamento > 0;
}
string Cartao::getAsString() const
{
ostringstream oss;
oss << "(numero " << numero << " saldo: " << saldo << " tarifario " << tarifario->getNome() << ")";
return oss.str();
}
bool operator==(const Cartao& orig1, const Cartao& orig2)
{
return orig1.getNumero() == orig2.getNumero();
}
class Rede
{
string nome;
//tarifarios é uma classe abstracta
//logo não pode haver objectos de uma classe abstracta
//vector <Tarifario> tarifarios;
//e queremos ponteiros para a classe base, e uma coleção polimorfica
vector <Tarifario*> tarifarios;
//cartoes não tem derivadas
//e podia ser vector <Cartao> cartoes;
vector <Cartao*> cartoes;
Tarifario* procuraTarifario(const string& nome) const;
public:
Rede(const string& nome0);
//rede composição: qd a rede deixar de existir os tarifários tb deixam
Rede(const Rede& ob);
Rede & operator=(const Rede& ob); //tem uma dificuldade
~Rede();
void setNome(const string& nome0);
bool acrescentaTarifario(const string& nomeTarifario);
bool acrescentaCartao(long num, const string& nomeTarifa);
int procuraCartao(long i)const;
bool removeCartao(long i);
bool registaChamada(long numero, int duracao);
bool fazCarregamento(long numero, float quantia);
bool autorizaChamada(long n)const;
string getAsString() const;
};
ostream& operator<<(ostream& saida, const Rede& rede);
Tarifario* Rede::procuraTarifario(const string& nome) const
{
for(Tarifario *t : tarifarios)
{
if(t->getNome() == nome)
{
return t;
}
}
return nullptr;
}
Rede::Rede(const string& nome0):nome(nome0)
{
}
Rede::Rede(const Rede& ob)
{
*this = ob;
}
Rede& Rede::operator=(const Rede& ob) //immportante, complicado
{
//prevenção da auto atribuicao
if(this == &ob)
{
return *this;
}
//libertar mem. dinamica apontada pelo primeiro membro da atribuicao
//e esvaziar os vectores
for(Tarifario *t: tarifarios)
{
delete t;
}
tarifarios.clear();
for(Cartao *c: cartoes)
{
delete c;
}
cartoes.clear();
//copiar os dados do segundo membro da atribuição
nome = ob.nome;
for(Tarifario * t: ob.tarifarios)
{
tarifarios.push_back(t->duplica());
}
//depois de todos os tarifários do primeiro membro da atribuição copiados
for(Cartao *c: ob.cartoes)
{
Cartao* novo = new Cartao(*c);
//cópia do cartao
//que aponta para um tarifario do segundo membro da atribuicao
string nomeTarifario = c->getNomeTarifario();
//identifica do seu tarifario
//procura tarifario com nomeTarifario no vector do primeiro membro da atribuicao
Tarifario* t = procuraTarifario(nomeTarifario);
novo->setTarifario(t);
cartoes.push_back(novo);
}
}
Rede::~Rede()
{
//porque sao vectres de ponteiros para objectos dinamicos
for(Tarifario *t: tarifarios)
{
delete t;
}
for(Cartao *c: cartoes)
{
delete c;
}
//e o que o destrutor libetra
//o construtor por copia e o operador atribuicao tem que duplicar
cout << "destr da rede " << nome << endl;
}
void Rede::setNome(const string& nome0)
{
this->nome = nome0;
}
bool Rede::acrescentaTarifario(const string& nomeTarifario)
{
Tarifario* tarifario0 = procuraTarifario(nomeTarifario);
if(tarifario0 != nullptr)
{
return false;
}
Tarifario* novoTarifario = Tarifario::fabrica(nomeTarifario);
if(novoTarifario == nullptr)
{
return false;
}
tarifarios.push_back(novoTarifario);
return true;
}
bool Rede::acrescentaCartao(long num, const string& nomeTarifa)
{
if(procuraCartao(num) != -1)
{
return false;
}
Tarifario* tf = procuraTarifario(nomeTarifa);
if(tf == nullptr)
{
return false;
}
cartoes.push_back(new Cartao(num, tf));
return true;
}
int Rede::procuraCartao(long i) const
{
for(unsigned int indice = 0; indice < cartoes.size(); indice++)
{
if(cartoes[indice]->getNumero() == i)
{
return indice;
}
}
return -1;
}
bool Rede::removeCartao(long i)
{
int aux = procuraCartao(i);
if(aux == -1)
{
return false;
}
//relação de composição
delete cartoes[aux]; //libetra o objecto
cartoes.erase(cartoes.begin() + aux);//tira o ponteiro do vector
return true;
}
bool Rede::registaChamada(long numero, int duracao)
{
int aux = procuraCartao(numero);
if(numero == -1)
{
return false;
}
cartoes[aux]->registaChamada(duracao);
return true;
}
bool Rede::fazCarregamento(long numero, float quantia)
{
int aux = procuraCartao(numero);
if(aux== -1)
{
return false;
}
return cartoes[aux]->fazCarregamento(quantia);
}
bool Rede::autorizaChamada(long n) const
{
int aux = procuraCartao(n);
if(aux == -1)
{
return false;
}
return cartoes[aux]->autorizaChamada();
}
string Rede::getAsString() const
{
ostringstream oss;
oss << "\nRede: " << nome << endl << " tarifarios: ";
for(Tarifario *t : tarifarios)
{
oss << t->getNome() << "\t";
}
oss << "\nCartoes: " << endl;
for(Cartao *c : cartoes)
{
oss << c->getAsString() << endl;
}
return oss.str();
}
ostream& operator<<(ostream& saida, const Rede& rede)
{
saida << rede.getAsString();
return saida;
}
int main(){
Rede* rede = new Rede("meo");
rede->acrescentaTarifario("Tagarela");
rede->acrescentaTarifario("FalaPouco");
rede->acrescentaCartao(10, "Tagarela");
rede->acrescentaCartao(20, "FalaPouco");
cout << rede->getAsString();
rede->removeCartao(10);
cout << rede->getAsString();
delete rede;
cout << "\nfim do main" << endl;
return 0;
}
Tags : apontamentos, c++11, Learn C plus plus, poo_lab_pt6, poof
0 thoughts on “herança e polimorfismo”