classes cujos objectos interagem de forma bidirecional

………..ficha6, exercicio1 (a18)

#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <regex>
#include <initializer_list>
#include <fstream>

using namespace std;

class Aquario;

class Peixe
{
	string nomeEspecie;
	string cor;
	int peso;
	int numSerie;
	int estadio; //0, normal, 1, emagrece, 2,3,4,5 nao come, 6 morre

	static int sequencia;
	//constantes iguais para todos:
	static const int LIMITE_PESO = 50;
	static const int INICIAL_PESO = 10;
	
public:
	Peixe(string nomeEspecie0, string cor0="cinzento");
	//posso e controlo total:
	//composição: destrutor a lierbtar os peixes, construtor pro copia e operador atribuição a duplicar aquilo que o destrutor destroi

	string getNomeEspecie() const;
	void setNomeEspecie(const string& nome_especie);
	string getCor() const;
	void setCor(const string& cor);
	int getPeso() const;
	void setPeso(const int peso);
	int getNumSerie() const;
	void setNumSerie(const int num_serie);
	int getEstadio() const;
	void setEstadio(const int estadio);

	bool isVivo()const;
	void alimentar(int quant, Aquario* aquario);
	
	string getAsString()const;
};

Peixe::Peixe(string nomeEspecie0, string cor0):nomeEspecie(nomeEspecie0), cor(cor0), peso(INICIAL_PESO), numSerie(++sequencia), estadio(0)
{
}

string Peixe::getNomeEspecie() const
{
	return nomeEspecie;
}

void Peixe::setNomeEspecie(const string& nome_especie)
{
	nomeEspecie = nome_especie;
}

string Peixe::getCor() const
{
	return cor;
}

void Peixe::setCor(const string& cor)
{
	this->cor = cor;
}

int Peixe::getPeso() const
{
	return peso;
}

void Peixe::setPeso(const int peso)
{
	this->peso = peso;
}

int Peixe::getNumSerie() const
{
	return numSerie;
}

void Peixe::setNumSerie(const int num_serie)
{
	numSerie = num_serie;
}

int Peixe::getEstadio() const
{
	return estadio;
}

void Peixe::setEstadio(const int estadio)
{
	this->estadio = estadio;
}

bool Peixe::isVivo() const
{
	return getEstadio() <= 5;
}

void Peixe::alimentar(int quant, Aquario* aquario)
{
	if(quant <= 0|| aquario == nullptr)
	{
		return;
	}
	if(estadio >0 && estadio<=5)
	{
		++estadio;
		return;
	}
	if(estadio>5)
	{
		return;
	}
	peso += quant;
	if(peso> LIMITE_PESO)
	{
		int probabilidade = rand() % 100;
		if(probabilidade < 50)
		{
			peso = LIMITE_PESO - INICIAL_PESO;
			aquario->nasceNovoPeixe(nomeEspecie, cor);
		}else
		{
			peso /= 2; //reduzido a metade
			estadio = 1;
		}
	}
	
}

string Peixe::getAsString() const
{
	ostringstream oss;

	oss << "\nPeixe: " << nomeEspecie << "\ncor: " << cor << "\npeso: " << peso << "\nnumSerie: " << numSerie << (estadio <= 5 ? " vivo" : " morto") << " estadio " << estadio << endl;
	return oss.str();
}

int Peixe::sequencia = 499; //num. para cada peixe


//relação bidirecional entre o Peixe e o Aquario
//include no CPP e declaração da classe no h

class Aquario
{
	//tem uma colecção de peixes
	vector<Peixe*> peixes;
	vector<Peixe*> novos; //o peixe usa para colocar os novos

	void eliminarMortos();
	void deslocaNovoParaAquario();
	int pesquisaPeixe(int numSerie0)const;
	
public:

	Aquario() = default; //os dois vectores são construidos por omissão, isto é ficam vazios na construção
	//e porque não existe nenhum ponteirp primitivo na classe
	//e no construtor por copia fica mais simples
	
	virtual ~Aquario();

	//quando um peixei e colocado no aquario, este assume
	//a sua posse e controlo total:
	Aquario(const Aquario& orig); //construtor por copia
	Aquario& operator=(const Aquario & orig); //operador atribuição
	
	void removePeixe(int numSerie);
	void alimentar(int quantidade0);
	void nasceNovoPeixe(string especie0, string cor0);

	bool acrescentaPeixeDoExterior(Peixe* peixe);

	string getAsString()const;
};



void Aquario::alimentar(int quantidade0)
{
	for(Peixe * p : peixes)
	{
		p->alimentar(quantidade0, this); //mt cuidado com isto, usa o vector<Peixe*> novos;
	}
	eliminarMortos();
	deslocaNovoParaAquario(); //sair do novo para o aquario normal
}

void Aquario::nasceNovoPeixe(string especie0, string cor0)
{
	novos.push_back(new Peixe(especie0, cor0));
}

bool Aquario::acrescentaPeixeDoExterior(Peixe* peixe)
{
	if (peixe == nullptr){
		return false;
	}
	//se o peixe estiver no aquario
	if(pesquisaPeixe(peixe->getNumSerie())!= -1)
	{
		return false;
	}
	//se ainda nao esta no aquario
	//criar um novo em mem dinamica, com new
	Peixe* p = new Peixe(*peixe); //faço copia local
	peixes.push_back(p);
	return true;
}

string Aquario::getAsString() const
{
	ostringstream oss;
	oss << "\nAquario; " << endl;
	for(Peixe * p: peixes)
	{
		oss << p->getAsString();
	}
	return oss.str();
}

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;
		}
	}
}

void Aquario::deslocaNovoParaAquario()
{
	for(Peixe * p: peixes)
	{
		peixes.push_back(p);
	}
	novos.clear();
}

Aquario::~Aquario()
{
	for(Peixe * p: peixes)
	{
		delete p;
	}
	for(Peixe * p: novos)
	{
		delete p;
	}
	cout << "\n~Aquario()" << endl;
}

Aquario::Aquario(const Aquario& orig)
{
	*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;
	}
	peixes.clear();
	//copiar a infor de orig, duplicando os objectos dinamicos Peixe
	for(Peixe * p: orig.peixes){
		peixes.push_back(new Peixe(*p));
	}
	for(Peixe * p: orig.peixes)
	{
		novos.push_back(new Peixe(*p));
	}
	return *this;
}

void Aquario::removePeixe(int numSerie)
{
	int qual = pesquisaPeixe(numSerie);
	if(qual == -1)
	{
		return;
	}
	delete peixes[qual];
	peixes.erase(peixes.begin() + qual);
}

int main()
{
	Peixe a("Robalo", "branco");
	Peixe b("Pescada");
	Peixe c("Salmao");

	Aquario* aq1 = new Aquario;

	aq1->acrescentaPeixeDoExterior(&a);
	aq1->acrescentaPeixeDoExterior(&b);
	aq1->acrescentaPeixeDoExterior(&c);

	cout << aq1->getAsString() << endl; // peso 10

	aq1->alimentar(20);

	cout << aq1->getAsString() << endl;  // peso 30
	aq1->alimentar(30);
	cout << aq1->getAsString() << endl;  // peso 60 e consequencias

	for (int i = 0; i < 6; ++i) {
		aq1->alimentar(1);
		cout << aq1->getAsString() << endl;
	}
	aq1->removePeixe(500);
	aq1->removePeixe(500);
	cout << aq1->getAsString() << endl;


	/// testa mem din
	Aquario* aq2 = new Aquario;
	aq2->acrescentaPeixeDoExterior(&a);
	aq2->acrescentaPeixeDoExterior(&a);
	aq2->acrescentaPeixeDoExterior(&a);

	cout << aq2->getAsString() << endl;

	*aq2 = *aq1;

	delete aq1;
	cout << " aq1:\n";
	cout << " aq2:\n";
	cout << aq2->getAsString() << endl;

	Aquario* aq3 = new Aquario(*aq2);
	delete aq2;
	cout << aq3->getAsString() << endl;
	delete aq3;

	cout << "\nfim do main" << endl;
	return 1;
}
Tags : , , , ,

0 thoughts on “classes cujos objectos interagem de forma bidirecional”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.