Day: September 6, 2021

excepções e vários

………..varios, exercicios excepções (a25)

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

using namespace std;

void funcao()
{
	double dX = -23.99;
	cout << "se funcao : antes excepcao " << endl;
	//se não houver excepções corre tudo bem
	//throw - 1; //sai aqui em estado de erro, lançada a execpção que não é tratata
	//ou
	//throw "um texto que e erro..";//sai aqui em estado de erro, lançada a execpção que não é tratata
	//ou
	//throw dX; //sai aqui em estado de erro, lançada a execpção que não é tratata
	cout << "se funcao : depois excepcao " << endl;
}

int main()
{
	cout << "\n inicio do main" << endl;
	funcao();
	cout << "\n fim do main" << endl;
	return 0;
}

………..varios, exercicios excepções (a25)

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

using namespace std;

class minhaExcepcao
{
	const char* const descricao;
public:
	minhaExcepcao(const char * const msg =0):descricao(msg){}
};


void funcao2()
{
	double dX = -23.99;
	cout << "se funcao : antes excepcao " << endl;
	//esta versão também não adianta..
	throw minhaExcepcao("algo aconteceu");
		
	cout << "se funcao : depois excepcao " << endl;
}

int main()
{
	cout << "\n inicio do main" << endl;
	funcao2();
	cout << "\n fim do main" << endl;
	return 0;
}

………..varios, exercicios excepções (a25)

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

using namespace std;

class Erro
{
	
};

void funcao3()
{
	cout << "se funcao : antes excepcao " << endl;
	try
	{
		//criação artifical de um erro de uma excepção com o uso do throw
		//ou
		//sendo executado o primeiro thorw e interrompe este try
		throw -1;
		//ou
		throw "primeira linha de comentario";
		//ou
		throw Erro(); //esta excepção não é tratada num catch, logo termina em erro, mesmo com a class estabelecida
		//ou
		//se nao for lançada nenhuma excepção então tbm não vai ser executado nenhum catch, e é porque está tudo bem
	}
	catch (int x)
	{
		//e é sempre executado no máximo um catch
		cerr << "apanho o valor int da excepcao: " << x << endl;
	}catch(const char * s)
	{
		cerr << "apanho o valor char da excepcao: " << s << endl;
	}
	cout << "se funcao : depois excepcao " << endl;
}

int main()
{
	cout << "\n inicio do main" << endl;
	funcao3();
	cout << "\n fim do main" << endl;
	return 0;
}

………..varios, exercicios excepções (a25)

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

using namespace std;


int main()
{
	cout << "\n inicio do main" << endl;
	try
	{
		throw - 1;
	}
	catch (int x)
	{
		//e é sempre executado no máximo um catch
		cerr << "apanho o valor int da excepcao: " << x << endl;
	}
	catch (double)
	{
		cerr << "apanho o valor double da excepcao: "<< endl;
	}
	catch (const string & str)
	{
		cerr << "apanho o valor string da excepcao: " << str << endl;
	}
	cout << "\n fim do main" << endl;
	return 0;
}

………..varios, exercicios excepções (a25)

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

using namespace std;
class denominadorNull
{
public:
	string sobre()
	{
		return string("denominador nulo\n");
	}
};

class foraDosLimites
{
public:
	string sobre()
	{
		return string("fora dos limites\n");
	}
};

double divisao(int numerador, int denominador)
{
	if(!denominador)
	{
		throw denominadorNull();
	}
	return static_cast<double>(numerador) / denominador;
}

int main()
{
	cout << "\n inicio do main" << endl;
	int a[4] = { 10,11,12,13 };
	int index = 1, d;
	while(index >=0)
	{
		cout << "qual o index: ";
		cin >> index;
		cout << "qual o denominador: ";
		cin >> d;
		try
		{
			//ou
			//throw "aaa";
			//ou
			if (index < 0 || index >= 4) throw foraDosLimites(); //e interrompe, não foi resolvido nao existe um catch
			//se correr bem continuo
			cout << "resultado: " << divisao(a[index], d) << endl;
		}
		catch (denominadorNull & dn)
		{
			cerr << dn.sobre(); //depois disto considera-se resolvido
		}
		catch(foraDosLimites & fl)
		{
			cerr << fl.sobre(); //depois disto considera-se resolvido
		}
		catch (...) //apanha todos os outros erros
		{
			cerr << "qualquer outro erro\n"; //depois disto considera-se resolvido
		}
	}
	return 0;
}

………..varios, exercicios excepções (a25)

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

using namespace std;

class baseErro
{
public:
	virtual void oque()
	{
		cout << "baseErro" << endl;
	}
};


class derivadaErro : public baseErro
{
public:
	virtual void oque()
	{
		cout << "derivadaErro" << endl;
	}
};

void funcao6()
{
	throw derivadaErro();
}

int main()
{
	try
	{
		funcao6();
	}
	catch (baseErro b) //não é usada a derivada mas sim a base, 
		//não existe neste caso o polimorfismo
	{
		b.oque();
	}
	try {
		funcao6();
	}
	catch (baseErro & b) //convem passar por referencia para existir o polimorfismo
		//porque é passado por referencia, surgre assim o erro da derivada
		//e para que não se faça mais uma copia da excepção que foi lançada
	{
		b.oque();
	}
	return 0;
}

………..varios, exame1920_epocanormal (a25)

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

using namespace std;

class Bilhete
{
	string passageiro;
	int passaporte;
	string & companhia; //obrigatoria ser na lista de inicialização, se for & e const
	vector<int> id_malas;

	//Acrescentar bagagens ao bilhete (representadas pelos seus ID e sem repetir):
	int pesquisa(int id)const;
	
public:
	//ou 1
	//Bilhete(string passageiro0, int passaporte0, string & companhia0, vector<int> id_malas0);
	//ou 2
	Bilhete(string passageiro0, int passaporte0, string& companhia0, initializer_list<int> id_malas0);


	//lidar com a atribuir objectos b1=b2
	Bilhete& operator=(const Bilhete& ob);

	//Acrescentar bagagens ao bilhete (representadas pelos seus ID e sem repetir):
	//operador que pode ser membro
	Bilhete& operator <<(int id); //por estar em cadeia
	//ou
	//void operator <<(int id); //se não estivesse em cadeia

	//Remover todas as bagagens com id superior a um indicado): 
	Bilhete& operator -=(int id); //por estar em cadeia
	
	//extra
	string getAsAstring()const;
};
//Mostrar o conteúdo no ecrã da forma (bilhete1 e bilhete2 são objetos da classe Bilhete): 
ostream& operator<<(ostream& saida, const Bilhete & ob);


//Acrescentar bagagens ao bilhete (representadas pelos seus ID e sem repetir):
int Bilhete::pesquisa(int id) const
{
	for(unsigned int i = 0; i< id_malas.size(); i++)
	{
		if(id == id_malas[i])
		{
			return i;
		}
	}
	return -1;
}

//Acrescentar bagagens ao bilhete (representadas pelos seus ID e sem repetir):
Bilhete& Bilhete::operator<<(int id)
{
	int pos = pesquisa(id);
	if(pos == -1)
	{
		//não está lá o id
		id_malas.push_back(id);
	}
	//senão não faço nada
	return  *this; // pedido em cadeia, o retorno é *this
}

//Remover todas as bagagens com id superior a um indicado): 
Bilhete& Bilhete::operator-=(int id)
{
	for(auto it= id_malas.begin(); it != id_malas.end(); )
	{
		if(*it >id)
		{
			it = id_malas.erase(it);
		}else
		{
			++it;
		}
	}
	return *this;
}

//ou
//void Bilhete::operator<<(int id) //se não estivesse em cadeia

//ou 1
//Bilhete::Bilhete(string passageiro0, int passaporte0, string& companhia0, vector<int> id_malas0) : passageiro(passageiro),
//passaporte(passaporte),
//companhia(companhia),
//id_malas(id_malas)
//{
//}
//ou 2, versão "mais complicada"
Bilhete::Bilhete(string passageiro0, int passaporte0, string& companhia0, initializer_list<int> id_malas0) : passageiro(passageiro0),
passaporte(passaporte0),
companhia(companhia0)
{
	//para lidar com o initializer_list
	for(auto & m : id_malas0)
	{
		id_malas.push_back(m);
	}
}

//lidar com a atribuir objectos
Bilhete& Bilhete::operator=(const Bilhete& ob)
{
	//evitar autoatribuição
	if(this == &ob)
	{
		return  *this;
	}
	//pode-se atribuir tudo menos a companhia, i.e. referencias e const
	passageiro = ob.passageiro;
	passaporte = ob.passaporte;
	id_malas = ob.id_malas;
	return *this;
}



//extra
string Bilhete::getAsAstring() const
{
	ostringstream oss;

	oss << "Passageiro: " << passageiro << " Passaporte: " << passaporte << " Companinha: " << companhia << "mala:" << endl;
	for (int i : id_malas)
	{
		oss << " " << i;
	}
	oss << endl;
	return oss.str();
}

//Mostrar o conteúdo no ecrã da forma (bilhete1 e bilhete2 são objetos da classe Bilhete): 
ostream& operator<<(ostream& saida, const Bilhete& ob)
{
	saida << ob.getAsAstring();
	return saida;
}


int main()
{
	//alinea 6.
	//string & companhia;  exige uma variavel
	string aux_nome("tap");
	//ou 1 ou 2
	Bilhete b1("nome Passageiro", 123, aux_nome, {1,2,3,4}); //{1,2,3,4} com initializer_list
	cout <<b1.getAsAstring(); 
	//para atribuir objectos
	string aux_nome2("fly");
	Bilhete b2("outro Passageiro",456, aux_nome2, {5,6,7,8}); 
	cout << b2.getAsAstring();

	//atribuir objectos b1 = b2
	//não é possivel por existe objectos com membros objectos com referencia (&) ou const
	//assim b1=b2 dá erro, é a atribuição default
	//solução: operador atribuição e operator
	b1 = b2;
	cout << b1.getAsAstring();

	//Mostrar o conteúdo no ecrã da forma (bilhete1 e bilhete2 são objetos da classe Bilhete): 
	cout << "\nPassageiro 1 : " << b1 << "\nPassageiro 2" << b2;

	//Acrescentar bagagens ao bilhete (representadas pelos seus ID e sem repetir):
	b1 << 123 << 789 << 123;
	cout << "\nPassageiro 1 acrescentou: " << b1;

	//Remover todas as bagagens com id superior a um indicado):
	(b1 -= 40) -= 35;
	cout << "\nPassageiro 1 removeu: " << b1;
	
	cout << "\nfim do main" << endl;
	return 0;
}

………..varios, exame1920_epocanormal (a25)

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

using namespace std;
//antes
/*
class Doutor {
	string nome;
public:
	Doutor(const string& n) :nome(n) {}
	string getNome()const { return nome; }
};
class Engenheiro {
	string nome;
public:
	Engenheiro(const string& n) :nome(n) {}
	string getNome()const { return nome; }
};

class Empresa {
	vector<Doutor> doutores;
	vector<Engenheiro> engenheiros;
public:
	Empresa() {
		doutores.push_back(Doutor("D1"));
		doutores.push_back(Doutor("D2"));
		engenheiros.push_back(Engenheiro("E1"));
		engenheiros.push_back(Engenheiro("E2"));
	}
	void cumprimentar() {
		for (auto& d : doutores) {
			cout << "Bom dia Doutor " << d.getNome() << endl;
		}

		for (auto& e : engenheiros) {
			cout << "Bom dia Engenheiro " << e.getNome() << endl;
		}
	}
	void removeDoutor(string nome) {
		// remove o doutor com esse nome do seu vector
	}
	void removeEngenheiro(string nome) {
		// remove o engenheiro com esse nome do seu vector
	}
};
*/
//depois corrigido
//class abstracta
class Funcionario
{
	string nome;
public:
	Funcionario(string nome0) :nome(nome0){}
	virtual void cumprimentar() const = 0;
	string getNome()const
	{
		return nome;
	}
	//para funionar o destutor, construtor por copia e operador atribuição
	virtual Funcionario* duplica()const = 0;
};

class Doutor: public Funcionario
{
public:
	Doutor(const string& nome0)
		: Funcionario(nome0)
	{
	}

	void cumprimentar() const override
	{
		cout << "Bom dia Doutor " << getNome() << endl;
	}

	Funcionario* duplica() const override
	{
		return new Doutor(*this);
	}
};

class Engenheiro : public Funcionario
{
public:
	Engenheiro(const string& nome0)
		: Funcionario(nome0)
	{
	}

	void cumprimentar() const override
	{
		cout << "Bom dia Engenheiro " << getNome() << endl;
	}

	Funcionario* duplica() const override
	{
		return new Engenheiro(*this);
	}
};

class Empresa {
	vector<Funcionario*> funcionarios;
	int pesquisa(string nome) const
	{
		for (unsigned int i = 0; i < funcionarios.size(); i++)
		{
			if (nome == funcionarios[i]->getNome())
			{
				return i;
			}
		}
		return -1;
	}
public:
	Empresa() {
		funcionarios.push_back(new Doutor("D1"));
		funcionarios.push_back(new Doutor("D2"));
		funcionarios.push_back(new Engenheiro("E1"));
		funcionarios.push_back(new Engenheiro("E2"));
	}
	void cumprimentar() {
		for (auto& d : funcionarios) {
			d->cumprimentar();
		}
	}

	void removerNome(string nome0)
	{
		int pos = pesquisa(nome0);
		if(pos == -1)
		{
			return;
		}
		//existe posso exclucivsa, eliminar o objecto de mem dinamica
		delete funcionarios[pos];
		//remover o ponteiro
		funcionarios.erase(funcionarios.begin() + pos);
	}
	//e existe propriedade exclusiva da empresa
	//fazer destrutor, construtor por copia e operador atribuição e duplica (esta em funcionarions)
	~Empresa()
	{
		for(auto f: funcionarios)
		{
			delete f;
		}
	}
	//construtor por copia
	Empresa(const Empresa& ob)
	{
		*this = ob; //apenas, porque não existem ponteiros primitivos
	}
	//operador atribuição
	Empresa &operator=(const Empresa &ob)
	{
		if(this ==&ob)
		{
			return *this;
		}
		for(auto f: funcionarios)
		{
			delete f;
		}
		funcionarios.clear();
		for(auto f: ob.funcionarios)
		{
			//depois de feitos os duplicas
			funcionarios.push_back(f->duplica());
		}
		return *this;
	}
};

int main() {
	Empresa empresa;
	empresa.cumprimentar();

	Empresa empresa2 = empresa;
	empresa2.removerNome("E1");
	empresa2.removerNome("D2");
	empresa2.cumprimentar();

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

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 : , , , ,

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 : , , , ,

objetos dinâmicos, matrizes dinâmicas, classes com construtores por cópia, operador de atribuição e destrutor

………..ficha5, exercicio1 (a15)

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

using namespace std;

class MSG
{
	string mensagem;
public:
	//	MSG(const string & s);
	MSG(const string& s="por omissao"); //d)
	~MSG();
};

MSG::MSG(const string& s):mensagem(s)
{
	cout << "ola " << mensagem << "\n";
}

MSG::~MSG()
{
	cout << "adeus " << mensagem << endl;
}

MSG * func(string s)
{
	MSG* p = new MSG(s);
	cout << "\n func: criado um objecto " << s << endl;
	return p; //retornamos uma copia, que é o valor do endereço
}

int main()
{
	//a) 
	//MSG * a = new MSG("AAAA");
	//MSG * b = new MSG("BBBB");
	////para destruir o new só aplicando o delete
	//cout << "\ndestruir..";
	//delete a; //destroi apenas o objecto dinamico, não o ponteiro
	//cout << "\ndestruir..";
	//delete b;
	//
	////um objecto que nao é dinamico
	//MSG c("CCCC");

	//a = new MSG("outro"); //o ponteiro a continua disponivel!
	//delete a;

	//c usar a func(a,b)
	//MSG* a = func("AAAA");
	//MSG* b = func("BBBB");
	//delete a;
	//delete b;
	
	//d)
	MSG* v = new MSG[3]; // com este construtor MSG(const string & s); nao funciona
	//só funciona com construtor por omissão
	MSG* v0 = new MSG[2]{ {"primeiro"}, {"segundo"} };

	//e)
	delete [] v;
	delete [] v0;

	//não se pode libertar espaço do MSG* v = new MSG[3];
	//quando se liberta é todos de uma vez
	
	cout << "\nfim do main" << endl;
	return 0;
}

………..ficha5, exercicio2 (a15, a16)

#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 |
+---
*/

class ABC
{
	char* p;
public:
	ABC(const char* s);
	~ABC();

	//c
	const char* getConteudo() const;
	//c) construtor por copia
	ABC(const ABC& ob);
	//c) operador atribuição
	ABC& operator=(const ABC & ob);
};

ABC::ABC(const char* s)
{
	p = new char[strlen(s) + 1];
	//construtor cria, composição
	strcpy(p, s);
	cout << "\nconstruindo .." << p << endl;
}

ABC::~ABC()
{
	cout << "\ndestruindo .." << p << endl;
	delete[] p;
}

const char* ABC::getConteudo() const
{
	return p;
}

//ABC::ABC(const ABC& ob) //c) versão um
//{
//	p = nullptr;
//	//ver se estamos a copiar uma string vazia
//	if(ob.p == nullptr || strlen(ob.p)==0)
//	{
//		return;
//	}
//	//alocar espaco para copiar a string da origem da copia
//	p = new char[strlen(ob.p) + 1];
//	//copiar para o proprio espaco
//	strcpy(p,ob.p);
//
//	cout << "\nconstrutor por copia: " << p << endl;
//}

ABC& ABC::operator=(const ABC& ob) //c)
{
	//operador atribuição tem:
	//prevenção da auto atribuição
	if (this == &ob) {
		return *this;
	}
	//libertacao de memoria apontada pelo prim membro de atribuição
	delete[]p; //ponteiro que tem lixo
	//limpar objecto
	p = nullptr;
	//se estamos a copiar uma string vazia
	if(ob.p == nullptr || strlen(ob.p)==0)
	{
		return *this;
	}
	//alocar espaco para copiar a string do segundo membro
	p = new char[strlen(ob.p) + 1];
	//copiar a string do seg membro para um espaco proprio
	strcpy(this->p, ob.p);
	cout << "\nOperador atribuicao ";
	
	return *this;
}

//c) alternativa versao dois
//construtor por copia à custa do operador atribuição
ABC::ABC(const ABC& ob)
{
	p = nullptr;
	*this = ob; //ao fazer esta atribuição chama.se o operator=
	cout << "\n CCop " << (p != nullptr ? p : nullptr) << " - " << ob.p << endl;
}


//b
void gastaMemoria()
{
	ABC temp("\nTexto temporario que ocupa espaco");
}

//c)
void func(ABC a)
{
	//o a é passado por valor
	//o a é criado pro copia de y, com o construtor por cópia
	//o construtor automatico, faz copia de membro a membro
}

void func()
{
	ABC a("aaa");
	ABC b("bbb");
	a = b;
}

int main()
{
	//b
	//for(unsigned int i = 0; i<10 ; i++)
	//{
	//	gastaMemoria();
	//}
	
	//c
	//a classe não tem construtor por cópia
	//a classe não tem operador de atribuição
	//apos o construtor por copia
	ABC y("ola y");
	cout << "conteudo do y: " << y.getConteudo() << endl;
	func(y);
	cout << "conteudo do y: " << y.getConteudo() << endl;
	//apos o operador de atribuição e a versao dois
	func();
		
	cout << "\nfim do main" << endl;
}

………..ficha5, exercicio5 (a16)

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

using namespace std;
//versão matriz dinamica
class Pessoa {
	string nome;
	long bi;
	long nif;

	void setBi(long b);
public:
	Pessoa() = delete;
	Pessoa(const string& s, long b, long n);
	string getNome()const;
	void setNome(const string& n);
	long getBi()const;
	long getNif()const;
	void setNif(long t);
	string getAsString()const;

};

Pessoa::Pessoa(const string& s, long b, long n)
	: nome(s), bi(b), nif(n) {
}

string Pessoa::getNome()const {
	return nome;
}

void Pessoa::setNome(const string& n) {
	nome = n;
}

long Pessoa::getBi()const {
	return bi;
}

void Pessoa::setBi(long b) {
	bi = b;
}

long Pessoa::getNif()const {
	return nif;
}

void Pessoa::setNif(long t) {
	nif = t;
}

string Pessoa::getAsString()const {
	ostringstream oss;
	oss << "\nNome: " << nome
		<< "\nBi: " << bi
		<< "\nNif: " << nif << endl;
	return oss.str();
}

	
class Clube {
	Pessoa** socios; //vector <Pessoa *> socios;
	int tam;
public:
	Clube(int t);
	~Clube();
	void setMembroDoclube(Pessoa* p, int pos);

	//construtor por copia
	Clube(const Clube& ob);
	//operador atribuição
	Clube & operator=(const Clube & ob);

	string getAsString() const;
};


Clube::Clube(int t)
{
	tam = t > 0 ? t : 0;
	if(tam == 0)
	{
		socios = nullptr;
		return;
	}
	socios = new Pessoa * [tam]; //tam, é um array tam, de tam Pessoa *.
	if (socios == nullptr) {
		tam = 0;
		return;
	}
	for (unsigned int i = 0; i < tam; i++)
		socios[i] = nullptr; //tudo igual a nulltpr
}

Clube::~Clube()
{
	delete[]socios; //liberta o array dinamico dos ponteiros
	//nao existe o ciclo for para deletar as pessoas
	//ninguem toca nas pessoas
}

//v1
//void Clube::setMembroDoclube(Pessoa* p, int pos)
//{
//	socios[pos] = p; //socios 0 = endereço de p
//}

//v2
void Clube::setMembroDoclube(Pessoa* p, int pos)
{
	if(pos >= 0 && pos < tam && socios[pos] == nullptr)
	{
		socios[pos] = p;
	}
}

Clube::Clube(const Clube& ob)
{
	//limpar os ponteiros aos quais o operador atribuicao vai fazer delete
	socios = nullptr;
	tam = 0;
	//aplicar o operador atribuição
	*this = ob;
}

Clube & Clube::operator=(const Clube& ob)
{
	//prevenção da auto atribuição
	if(this == &ob)
	{
		return *this;
	}
	//limpar memoria velha
	delete[] socios; //a seguir é necessário o nullptr
	socios = nullptr;
	tam = 0;

	//se a origem da copia for um clube sem socios
	if(ob.socios == nullptr || ob.tam ==0 )
	{
		return * this;
	}
	//se a origem da copia for um clube com socios
	socios = new Pessoa * [ob.tam];
	//copiar o tam
	tam = ob.tam;
	//copiar os ponteiros
	for(unsigned int i = 0; i < tam; i++)
	{
		//nao se duplicam os cosios porque a relacao entre clube e socios e de agregacao
		//o destrutor tambem nao os destroi
		socios[i] = ob.socios[i];
	}
	return *this;
}

string Clube::getAsString() const
{
	ostringstream oss;
	oss << "\nTam: " << tam << endl;
	for (unsigned int i = 0; i < tam; i++) {
		if (socios[i] != nullptr) {
			oss << socios[i]->getAsString() << endl;
		}
	}
	
	return oss.str();
}


int main()
{
	//agregacao entre o clube e as pessoas
	//relação entre o clube e o array de ponteiros é de composição
	
	Pessoa a("aaa",1,111), b("bbb", 2, 222);
	Clube* clube1 = new Clube(50);
	clube1->setMembroDoclube(&a, 0);
	clube1->setMembroDoclube(&b, 1);

	cout << "Clube1: " << clube1->getAsString();
	
	Pessoa c("ccc", 3, 333), d("ddd", 4, 444);
	Clube* clube2 = new Clube(10);
	clube2->setMembroDoclube(&a, 0);
	clube2->setMembroDoclube(&b, 1);
	clube2->setMembroDoclube(&c, 2);
	clube2->setMembroDoclube(&d, 3);

	cout << "Clube2: " << clube2->getAsString();

	*clube1 = *clube2; //atribuir os apontados
	delete clube2;
	cout << "Clube2 depois: " << clube1->getAsString();

	//copia do apontado
	Clube clube3(*clube1);
	cout << "Clube3 depois: " << clube3.getAsString();
	
	cout << "\nfim do main" << endl;
}

………..ficha5, exercicio5 (a16,)

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

using namespace std;
//versão vector 
class Pessoa {
	string nome;
	long bi;
	long nif;

	void setBi(long b);
public:
	Pessoa() = delete;
	Pessoa(const string& s, long b, long n);
	string getNome()const;
	void setNome(const string& n);
	long getBi()const;
	long getNif()const;
	void setNif(long t);
	string getAsString()const;

};

Pessoa::Pessoa(const string& s, long b, long n)
	: nome(s), bi(b), nif(n) {
}

string Pessoa::getNome()const {
	return nome;
}

void Pessoa::setNome(const string& n) {
	nome = n;
}

long Pessoa::getBi()const {
	return bi;
}

void Pessoa::setBi(long b) {
	bi = b;
}

long Pessoa::getNif()const {
	return nif;
}

void Pessoa::setNif(long t) {
	nif = t;
}

string Pessoa::getAsString()const {
	ostringstream oss;
	oss << "\nNome: " << nome
		<< "\nBi: " << bi
		<< "\nNif: " << nif << endl;
	return oss.str();
}

class Clube {
	//Pessoa** socios;
	vector <Pessoa *> socios;
	
	int tam;
public:
	Clube(int t);
	//~Clube();
	void setMembroDoclube(Pessoa* p, int pos);

	//construtor por copia
	//Clube(const Clube& ob);
	//operador atribuição
	//Clube& operator=(const Clube& ob);
	//Nesta versao não é preciso construtor por copia, atribuição e destrutor
	//Por nesta classe so usarmos ponteiros, e não ciramos nenhuma memoria dinamica, logo não existe necessidade de cópiar nada
	string getAsString() const;
};

//Clube::Clube(int t)
//{
//	tam = t > 0 ? t : 0;
//	if (tam == 0)
//	{
//		socios = nullptr;
//		return;
//	}
//	socios = new Pessoa * [tam]; //tam, é um array tam, de tam Pessoa *.
//	if (socios == nullptr) {
//		tam = 0;
//		return;
//	}
//	for (unsigned int i = 0; i < tam; i++)
//		socios[i] = nullptr; //tudo igual a nulltpr
//}

Clube::Clube(int t)
{
	for (unsigned int i = 0; i < t; i++) {
		socios.push_back(NULL);
	}
}

//v1
//Clube::~Clube()
//{
//	delete[]socios; //liberta o array dinamico dos ponteiros
//	//nao existe o ciclo for para deletar as pessoas
//	//ninguem toca nas pessoas
//}

//v1
//void Clube::setMembroDoclube(Pessoa* p, int pos)
//{
//	socios[pos] = p; //socios 0 = endereço de p
//}

//v2
//void Clube::setMembroDoclube(Pessoa* p, int pos)
//{
//	if (pos >= 0 && pos < tam && socios[pos] == nullptr)
//	{
//		socios[pos] = p;
//	}
//}

//v3 vestores
void Clube::setMembroDoclube(Pessoa* p, int pos)
{
	if (pos >= 0 && pos < socios.size() && socios[pos] == NULL) {
		socios[pos] = p; // Notar que o obj. Pessoa e visto pelo Clube
	}
}

//Clube::Clube(const Clube& ob)
//{
//	//limpar os ponteiros aos quais o operador atribuicao vai fazer delete
//	socios = nullptr;
//	tam = 0;
//	//aplicar o operador atribuição
//	*this = ob;
//}
//
//Clube& Clube::operator=(const Clube& ob)
//{
//	//prevenção da auto atribuição
//	if (this == &ob)
//	{
//		return *this;
//	}
//	//limpar memoria velha
//	delete[] socios; //a seguir é necessário o nullptr
//	socios = nullptr;
//	tam = 0;
//
//	//se a origem da copia for um clube sem socios
//	if (ob.socios == nullptr || ob.tam == 0)
//	{
//		return *this;
//	}
//	//se a origem da copia for um clube com socios
//	socios = new Pessoa * [ob.tam];
//	//copiar o tam
//	tam = ob.tam;
//	//copiar os ponteiros
//	for (unsigned int i = 0; i < tam; i++)
//	{
//		//nao se duplicam os cosios porque a relacao entre clube e socios e de agregacao
//		//o destrutor tambem nao os destroi
//		socios[i] = ob.socios[i];
//	}
//	return *this;
//}

//v1
//string Clube::getAsString() const
//{
//	ostringstream oss;
//	oss << "\nTam: " << tam << endl;
//	for (unsigned int i = 0; i < tam; i++) {
//		if (socios[i] != nullptr) {
//			oss << socios[i]->getAsString() << endl;
//		}
//	}
//
//	return oss.str();
//}
//v2 vectores
string Clube::getAsString()const {
	ostringstream oss;
	oss << "\nTam: " << socios.size() << endl;
	for (unsigned int i = 0; i < socios.size(); i++) {
		if (socios[i] != nullptr) {
			oss << socios[i]->getAsString() << endl; // tem de uusar ->
		}
	}
	return oss.str();
}
int main()
{
	//agregacao entre o clube e as pessoas
	//relação entre o clube e o array de ponteiros é de composição

	Pessoa a("aaa", 1, 111), b("bbb", 2, 222);
	Clube* clube1 = new Clube(50);
	clube1->setMembroDoclube(&a, 0);
	clube1->setMembroDoclube(&b, 1);

	cout << "Clube1: " << clube1->getAsString();

	Pessoa c("ccc", 3, 333), d("ddd", 4, 444);
	Clube* clube2 = new Clube(10);
	clube2->setMembroDoclube(&a, 0);
	clube2->setMembroDoclube(&b, 1);
	clube2->setMembroDoclube(&c, 2);
	clube2->setMembroDoclube(&d, 3);

	cout << "Clube2: " << clube2->getAsString();

	*clube1 = *clube2; //atribuir os apontados
	delete clube2;
	cout << "Clube2 depois: " << clube1->getAsString();

	//copia do apontado
	Clube clube3(*clube1);
	cout << "Clube3 depois: " << clube3.getAsString();

	cout << "\nfim do main" << endl;
}

………..ficha5, exercicio7 (a17)

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

using namespace std;

//relação da agenda com contacto é de composição
//qd a agenda for destruida os contactos tb são
//contactos: objecto em memória dinamica
//usar vectores, sem necessidade de indicar quantidades
//matriz dinamics de ponteiros


class Contacto
{
	string nome;
	unsigned int tel;
public:
	Contacto() = delete;
	Contacto(const string& s, unsigned int t);
	string getNome()const;
	void setNome(const string& n);
	unsigned int getTel()const;
	void setTel(unsigned int t);
	string getAsString()const;
};

Contacto::Contacto(const string& s, unsigned t):nome(s), tel(t)
{
}

string Contacto::getNome() const
{
	return  nome;
}

void Contacto::setNome(const string& n)
{
	this->nome = n;
}

unsigned Contacto::getTel() const
{
	return tel;
}

void Contacto::setTel(unsigned t)
{
	this->tel = t;
}

string Contacto::getAsString() const
{
	ostringstream oss;
	oss << "Contacto " << " Nome: " << nome << "\tTel: " << tel;
	return oss.str();
}


class Agenda
{
	string nome;
	vector<Contacto*> contactos; //vector de ponteiros
	//o objecto composto vai destruir a string e o vector de ponteiros
	//mas não os apontados, tem que haver um destrutor que faça a libertação dos apontados
	//pois não existe mais nada no programa que conheça os apontados (ver destrutor da Agenda)
	int pesquisa(const string& s)const;
public:
	Agenda(const string& nome0);
	Agenda(const Agenda& ob); //construtor por copia
	Agenda& operator=(const Agenda& ob); //operador =
	~Agenda();
	string getNome()const;
	void setNome(const string& nome0);
	bool acrescentaContacto(const string& n, unsigned int i);
	bool removeContacto(const string& n);
	string getAsString()const;
	const Contacto * getContacto(const string& s);

	bool gravaContactosEmFicheiroDeTexto();
	bool lerContactosDeFicheiroDeTexto();
	
};


int Agenda::pesquisa(const string& s) const
{
	for(unsigned int i = 0 ; i < contactos.size(); i++)
	{
		if(contactos[i]->getNome() == s)
		{
			return i;
		}
	}
	return -1;
}

Agenda::Agenda(const string& nome0):nome(nome0)
{
}

Agenda::Agenda(const Agenda& ob)
{
	//existem dois membros da classe: nome e vector
	*this = ob;
	cout << "\n CCop " << ob.getAsString() << endl;
}

Agenda& Agenda::operator=(const Agenda& ob)
//a.operator(b), a apontado por this ou *this,
//b é recebido pela ref. ob
{
	//testar a auto atribuição 
	if(this == &ob)
	{
		return *this;
	}
	//destruir os objectos apontados pelo primeiro membro de atribuição
	for(Contacto * c: contactos)
	{
		delete c;
	}
	//esvaziar o vector contactos
	contactos.clear();
	//copiar o segundo membro da atribuição
	for(Contacto * c : ob.contactos)
	{
		Contacto* dupplicado = new Contacto(*c);
		contactos.push_back(dupplicado);
	}
	return *this;
}

Agenda::~Agenda()
{
	//obrigatório por ser relação de composição
	//e existe uma estrutura de vectores de ponteiros
	for(Contacto * c: contactos)
	{
		delete c;
	}
}

string Agenda::getNome() const
{
	return nome;
}

void Agenda::setNome(const string& nome0)
{
	this->nome = nome0;
}

bool Agenda::acrescentaContacto(const string& n, unsigned int t)
{
	int qual = pesquisa(n);
	if(qual != -1)
	{
		return false;
	}
	contactos.push_back(new Contacto(n, t));
	return true;
}

bool Agenda::removeContacto(const string& n)
{
	int qual = pesquisa(n);
	if(qual == -1)
	{
		return false;
	}
	delete contactos[qual]; //nunca sera erase, e primeiro faz-se sempre o erase e depois o delete
	//relação da classe é de composição: 1º deçete, 2º depois erase.
	//se a relação for de agregação é só o erase
	//sendo composição:
	//o delete: liberta a memoria dinamica apontada
	//o erase: tira a posição do vector, tira o ponteiro, erase será do vector
	//se fizer o delete e nao fizer o erase, o ponteiro fica apontar para lixo, e o destrutor vai fazer duplo delete, erro de execução
	//erase e depois o delete: erase da pos zero, e depois o delete de contactos zero.. não faz sentido
	contactos.erase(contactos.begin() + qual);
	return true;
}

string Agenda::getAsString() const
{
	ostringstream oss;
	
	oss << nome << endl;
	for(Contacto * p: contactos)
	{
		oss << endl << p->getAsString();
	}
	
	return oss.str();
}

const Contacto* Agenda::getContacto(const string& s)
{
	int qual = pesquisa(s);
	if(qual == -1)
	{
		return nullptr;
	}else
	{
		return contactos[qual];
	}
}

bool Agenda::gravaContactosEmFicheiroDeTexto()
{
	ofstream dados("dados.txt");
	if (!dados.is_open()) {
		return false;
	}

	for (unsigned int i = 0; i < contactos.size(); i++) {
		dados << contactos[i]->getTel()
			<< " " << contactos[i]->getNome() << endl;
	}

	dados.close();
	if (dados) {
		return true;
	}
	else return false;
}

bool Agenda::lerContactosDeFicheiroDeTexto()
{
	ifstream dados("dados.txt");
	string nome;
	unsigned int tel;
	string s;
	if (!dados.is_open()) {
		return false;
	}
	// ler dados de todas as pessoas
	// uma por linha
	while (!dados.eof()) {
		// ler string com os dados da pessoa
		getline(dados, s);

		istringstream iss(s);
		// ler dados da pessoa
		iss >> tel >> std::ws;
		getline(iss, nome);

		// se correu bem a leitura ...
		if (iss) {
			acrescentaContacto(nome, tel);
		}
	}
	dados.close();
	return true;
}

int main()
{
	Agenda* a1 = new Agenda("a minha agenda 2021");
	a1->acrescentaContacto("pedro", 1234);
	a1->acrescentaContacto("maria", 5678);
	cout << "\nAgenda: " << a1->getAsString() << endl;
	a1->gravaContactosEmFicheiroDeTexto();

	Agenda* a2 = new Agenda("a minha agenda 2022");
	a2->lerContactosDeFicheiroDeTexto();
	cout << "\nAgenda: " << a2->getAsString() << endl;

	Agenda* a3 = new Agenda("a minha agenda especial");
	*a3 = *a2; 
	delete a2;
	a3->removeContacto("maria");
	cout << "\nAgenda: " << a3->getAsString() << endl;
	
	cout << "\nsair do main" << endl;
	return 1;
}
Tags : , , , ,

operadores

………..ficha4, exercicio1 (a13, a14)

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

using namespace std;

//os operadores
//uso de operados de atribuiçao em situações de composição envolvendo memória dinâmica
//aumentar a clareza do código por exemplo a.multiplica(b) po a * b
//operadores podem ser globais ou membros
//p.e.: globaL operator++(a,b)
//p.e.: membro a.operator++(b)
/*
+---------------------------------------- + -------------------------- - +
| 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 |
+---------------------------------------- + -------------------------- - +
*/
//o retorno de um operador pode ser um valor ou uma cópia de algo
//se o objectivo é usar o resultado de um operador, então este deve ser uma referência para algo, não constante e que pode ser modificado 


class Fraccao
{
	int numerador;
	int denominador;
public:
	//explicit //se usado trancamos o construtor, fazendo com que tenhamos que usar implicitamente Fracca(a) , na main
	//explicit, indicar ao construtor que só trabalhar quando o mandarmos trabalhar
	Fraccao();
	Fraccao(int num);
	Fraccao(int num, int denom);

	int getNumerador() const;
	void setNumerador(const int numerador);
	int getDenominador() const;
	void setDenominador(const int denominador);
	
	string getAsString() const;

	//b v3
	Fraccao operator*(const Fraccao& f); //operador * membro

	//j)
	Fraccao & operator*=(const Fraccao& f); //operador *= membro, não pode ser void

	//m) membro, operador unário
	Fraccao & operator++(); //++a
	Fraccao  operator++(int n); //a++, int n, serve para poderem funcionar as duas, mesmo que nao faça nada

	//n) passamos uma fraccao mas a f recebe apenas um inteiro
	//operador de conversao
	operator int()const { return denominador/numerador; };

};

Fraccao::Fraccao()
{
	numerador = 0;
	denominador = 1;
}

Fraccao::Fraccao(int num) :numerador(num)
{
	denominador = 1;
}

Fraccao::Fraccao(int num, int denom):numerador(num)
{
	setDenominador(denom);
}

int Fraccao::getNumerador() const
{
	return numerador;
}

void Fraccao::setNumerador(const int numerador)
{
	this->numerador = numerador;
}

int Fraccao::getDenominador() const
{
	return denominador;
}

void Fraccao::setDenominador(const int denominador)
{
	if(denominador >0)
	{
		this->denominador = denominador;
	}else if(denominador ==0)
	{
		this->denominador = 1;
	}else
	{
		this->numerador = -this->numerador;
		this->denominador = -denominador;
	}
}

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

	oss << " ( " << numerador << " / " << denominador << " ) " << endl;
	
	return oss.str();
}

//b, v3
Fraccao Fraccao::operator*(const Fraccao& f)
{
	cout << "operator*(const Fraccao& f)\n";
	Fraccao prod(getNumerador() * f.getNumerador(), getDenominador() * f.getDenominador());
	return prod;
}

Fraccao & Fraccao::operator*=(const Fraccao & f)
{
	cout << "operator*=(const Fraccao & f)\n";
	numerador *= f.getNumerador();
	denominador *= f.getDenominador();
	return *this; 
}

Fraccao& Fraccao::operator++()
{
	numerador += denominador; //a fracao aumenta uma unidade
	return *this; //retorna objecto depois de incremento
}

Fraccao Fraccao::operator++(int n)
{
	Fraccao aux = *this; //grava para esta varavel auxiliar o objecto antes de incrementar
	numerador += denominador; //a fracção aumenta uma unidade
	return aux; //não pode ser por referencia, retorna-se a variavel local
}


//b, v1
Fraccao produto(const Fraccao& x, const Fraccao& y) //função global
{
	Fraccao prod(x.getNumerador() * y.getNumerador(), x.getDenominador() * y.getDenominador());
	return prod;
}
//b, v2
Fraccao operator*(const Fraccao& x, const Fraccao& y) //função global
{
	cout << "operator*(const Fraccao& x, const Fraccao& y)\n";
	Fraccao prod(x.getNumerador() * y.getNumerador(), x.getDenominador() * y.getDenominador());
	return prod;
}

//g
ostream & operator<<(ostream & saida, const Fraccao & ob)
{
	saida << ob.getAsString();
	return saida;
}

//extra
istream& operator>>(istream& entrada,  Fraccao& ob)
{
	int num, denom;
	entrada >> num, denom;
	if(entrada)
	{
		ob.setNumerador(num);
		ob.setDenominador(num);
	}
	return entrada;
}

//n)
void func(int n) {
	cout << n;  // aparece 2
}

//o) (a==b)
bool operator==(const Fraccao& op1, const Fraccao& op2);
bool operator==(const Fraccao& op1, const Fraccao& op2)
{
	return (op1.getNumerador() * op2.getDenominador() == op1.getDenominador() * op2.getNumerador());
}

int main()
{
	//a)
	/*Fraccao a(1, 2);
	Fraccao b(3);
	const Fraccao c(3, 4);

	cout << a.getAsString();
	cout << b.getAsString();
	cout << c.getAsString();*/

	//b) multiplicação de duas fraccoes
	//v1
	//Fraccao a(1, 2);
	//Fraccao b(3);
	//const Fraccao c(3, 4);
	//Fraccao a1;
	//a1 = produto(b,c); 
	//cout << a1.getAsString();
	//v2
	//a = b * c; // a  = operator(b,c); global
	//cout << a.getAsString();
	//v3 (estando as duas opções disponiveis, global ou membro, recai sobre o membro)
	//a = b * c;// a = b.operator*(c); membro
	//cout << a.getAsString();

	//c)
	//Fraccao a(1, 2);
	//Fraccao b(3);
	//const Fraccao c(3, 4);
	//a = a * b * c; //composição das funções, (a*b)*c
	//operator*(operator*(a,b),c)
	//cout << a.getAsString();

	//d e e)
	//Fraccao a(1, 2);
	//Fraccao b(3);
	//a = b * 4; //b.operator*(4)
	//cout << a.getAsString();
	//d e e) v2 construtor explicit
	//a = b * Fraccao(4); //só assim funcionaria
	//d e e) v3
	//Fraccao a(1, 2);
	//Fraccao b(3);
	//a = 4 * b; //funciona apenas o global, se for membro só se usado o explicit, Fraccao(4) * b;
	//cout << a.getAsString();

	//g) v1
	//Fraccao a(1, 2);
	//cout << a; //<<, operador binário, tem que ser operador global
	//cout está a invocar a nossa operação, cout é da classes ostream, não é da nossa classe, logo << tem que ser global
	//g e h) v2
	//Fraccao a(1, 2);
	//Fraccao b(3);
	//const Fraccao c(3, 4);
	//cout << a << b << c; //por ser global e ostream ao inves de void funciona em cadeia

	//i) ao inves de copia usar o valor, ostream & operator<<(ostream saida, const Fraccao & ob)
	//não dá...dá erro

	//extra
	//Fraccao a(1, 2);
	//Fraccao b(3);
	//cin >> a;
	//cout << a.getAsString();
	
	//j) a *= b
	//Fraccao a(1, 2);
	//Fraccao b(2,3);
	////a *= b;
	////operador global: operator*=(a,b)
	////operador membro: a.operator*=(b) //recomendada
	////*= te como retorno 
	//cout << "antes->" << " a: " << a << " b: " << b << endl;
	//a *= b;
	//cout << "depois->" << " a: " << a << " b: " << b << endl;
	//Fraccao a2(1, 2);
	//Fraccao b2(2, 3);
	//Fraccao c2(3, 4);
	//cout << "antes->" << " a2: " << a2 << " b2: " << b2 << " c2: " << c2 << endl;
	//a2 *=  b2 *= c2;
	//cout << "depois->" << " a2: " << a2 << " b2: " << b2 << " c2: " << c2 << endl;
	//Fraccao a3(1, 2);
	//Fraccao b3(2, 3);
	//Fraccao c3(3, 4);
	//cout << "antes->" << " a3: " << a3 << " b3: " << b3 << " c3: " << c3 << endl;
	//(a3 *= b3) *= c3;
	//cout << "depois->" << " a3: " << a3 << " b3: " << b3 << " c3: " << c3 << endl;

	//l) retornar referencia ou valor
	//Fraccao a(1, 2), b(2, 3), c(3, 4);
	//cout << "antes->" << " a: " << a << " b: " << b << " c: " << c << endl;
	//(a *= b) *= c;
	//cout << "depois->" << " a: " << a << " b: " << b << " c: " << c << endl;
	//// é suposto aparecer 6/24
	//cout << a;
	//cout << "expressao ((a *= b) *= c)" << ((a *= b) *= c) << endl;
	//retornar por referência Fraccao & Fraccao::operator*=(const Fraccao & f)
	//retornar por valor (é uma copia) Fraccao Fraccao::operator*=(const Fraccao & f)

	//m) posfixado, a++ e prefixado ++a
	//++a, global, operator++(a)
	//++a, membro, a.operator++() //não recebe nenhum argumento
	//prefixado
	//int n = 2;
	//cout << "++n= " << ((++n)) << endl; //3, e é possivel fazer uma atribuição (++n)=55, vem ++n=55
	//cout << "  n= " << n << endl; //3
	////posfixado
	//int n2 = 2;
	//cout << "n2++= " << ((n2++)) << endl; //2
	//cout << "  n2= " << n2 << endl; //3
	//Fraccao a(1, 2), b(2, 3), c(3, 4);
	//(++a) = c;
	//cout << ++a; //a.operator++() //sem argumento
	//cout << a; 
	//Fraccao a2(1, 2), b2(2, 3), c2(3, 4);
	//cout << a2++; //a.operator++(0) //0 é um argumento
	//cout << a2;

	//n)
	//const Fraccao f(7,3);
	//func(f);  // é passado automaticamente o valor 7/3
	//     	  // arredondado para baixo

	//o) if(a==b)
	//tem que existir o operador== que retorne um bool, e é global
	Fraccao a(1, 2), b(1, 2);
	if(a== b)
	{
		cout << "oi";
	}else
	{
		cout << "noi";
	}
		
	cout << "\nfim do main" << endl;
	return 0;
}

………..ficha4, exercicio3 (a14)

#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 |
+---
*/
class Automovel {
	const string matricula; //const para proibir atribuições
	string marca;
	string modelo;
	int ano;

	static int nAutomoveisCriados; //tem que ser inicializada fora da classe

public:
	Automovel(const Automovel& ob);
	Automovel(string matricula, string marca, string modelo, int ano);
	~Automovel();

	string getMatricula()const;
	string getMarca()const;
	string getModelo()const;
	int getAno()const;

	static int getNAutomoveisCriados();

	void setMarca(string marca);
	void setModelo(string modelo);
	void setAno(int ano);

	string getAsString()const;

	Automovel& operator=(const Automovel& ob); //retorna uma referencia para o primeiro membro da atribuição
};

int Automovel::nAutomoveisCriados = 0;

ostream& operator<<(ostream& saida, const Automovel& ob);

Automovel::Automovel(const Automovel& ob):matricula(ob.matricula), marca(ob.marca), modelo(ob.modelo), ano(ob.ano)
{
	cout << "\nConstrutor por copia";
	++nAutomoveisCriados; //tambem por copia, os construidos por cópia tb devem ser contados!
}

Automovel::Automovel(string matricula1, string marca1, string modelo1, int ano1): matricula(matricula1), marca(marca1),	modelo(modelo1), ano(ano1) {
	cout << "\nConstrutor com parametros";
	++nAutomoveisCriados;
}

Automovel::~Automovel() {
	cout << "\nDestruindo " << getAsString();
}

string Automovel::getMatricula()const {
	return matricula;
}
string Automovel::getMarca()const {
	return marca;
}
string Automovel::getModelo()const {
	return modelo;
}
int Automovel::getAno()const {
	return ano;
}

int Automovel::getNAutomoveisCriados()
{
	return nAutomoveisCriados;
}

void Automovel::setMarca(string marca1) {
	marca = marca1;
}
void Automovel::setModelo(string modelo1) {
	modelo = modelo1;
}
void Automovel::setAno(int ano1) {
	ano = ano1;
}

string Automovel::getAsString()const {
	ostringstream oss;
	oss << "\nAutomovel: " << matricula << "   " << marca << "   " << modelo << "   " << ano;
	return oss.str();
}

Automovel& Automovel::operator=(const Automovel& ob) {
	//
	if (this == &ob) {
		return *this;
	}
	cout << "\nOperador atribuicao ";
	//a matricula nao se altera no objecto destino da atribuição
	this->marca = ob.marca;
	this->ano = ob.ano;
	this->modelo = ob.modelo;
	return *this;
}

ostream& operator<<(ostream& saida, const Automovel& ob) {
	saida << ob.getAsString() << endl;
	return saida;
}

void f(Automovel  x) {
	cout << x << endl;
}

int main()
{
	Automovel a1("11-11-AA", "OPEL", "OMEGA", 2010);
	Automovel a2("22-22-BB", "FIAT", "PUNTO", 2011);

	Automovel a3 = a1; //a3 copia de a1, construtor por copia
	a1 = a2; //operador atribuição, mas havendo membros constantes, tem que se fazer o operador operator=
	//a1.operator=(a2)
	f(a1);
	return 1;
}
Tags : , , , ,

composição, agregação, vectores, ficheiros

………..ficha3, exercicio1 (a8)

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

using namespace std;

//"nao deve ser possivel construir objectos desta classe sem a indicacação.." não pode haver construtor por omissão
//"sem desrespeitar o encapsulamento.." gets e sets
//"as funções que permitem obter os dados devem poder ser chamadas sobre bjectos constantes" devem conter o const

class Ponto
{
private:
	//encapsulamento
	int x;
	int y;

public:
	//Ponto(int x0, int y0); //necessário introduzir coordenadas
	~Ponto();

	Ponto(int x0 = 0, int y0 = 0); //construtor por omissão, e)

	//extra
	/*Ponto()
	{
		x = rand() % 100;
		y = rand() % 100;
		cout << "\nponto " << getAsString();
	}*/
	
	
	int getX() const
	{
		return x;
	}

	void setX(const int x)
	{
		this->x = x;
	}

	int getY() const
	{
		return y;
	}

	void setY(const int y)
	{
		this->y = y;
	}

	double calculaDistancia(const Ponto & outro)const;
	
	string getAsString()const;
};

Ponto::Ponto(int x0, int y0)
{
	x = x0;
	y = y0;
	cout << "\nPonto(in x0, int y0) " << getAsString();
}

Ponto::~Ponto()
{
	cout << "\n~Ponto() " << getAsString();
}

double Ponto::calculaDistancia(const Ponto& outro) const
{
	//pitágoras, calculo da distância
	double dist = (x - outro.x) * (x - outro.x) + (y - outro.y) * (y - outro.y);
	return sqrt(dist);
}

string Ponto::getAsString() const
{
	ostringstream oss;
	oss << " ( " << x << " , " << y << " ) " << endl;
	return oss.str();
}

int main()
{
	Ponto a(1,1);
	Ponto b(2,2);

	cout << a.getAsString(); //as funções mmebros recebem um ponbteiro para o objectos que as invocou, daí tem acesso a  e b
	cout << a.calculaDistancia(b);

	//c)
	const Ponto c(5, 6); //agora só posso chamar funcções que sejam const
	cout << c.getAsString();
	cout << "c.getY(); " << c.getY();

	//d)
	Ponto tab_d[] = {Ponto(1,3), Ponto(2,4), Ponto(5,7)};
	
	//e) 	Ponto(int x0 = 0, int y0 = 0); //construtor por omissão, e)
	Ponto tab_e[3];

	
	cout << "\nfim do main" << endl;
	return 0;
}

………..ficha3, exercicio3 (a8, a9)

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

using namespace std;

//composição de objectos


class Ponto
{
	int x;
	int y;
public:
	//Ponto(); //construtor por omissao
	//Ponto(int x0, int y0);
	Ponto(int x0=0, int y0=0); //construtor por omissão
	Ponto(const Ponto& z);
	~Ponto();

	int getX() const
	{
		return x;
	}

	void setX(const int x)
	{
		this->x = x;
	}

	int getY() const
	{
		return y;
	}

	void setY(const int y)
	{
		this->y = y;
	}

	string getAsString() const;
};

Ponto::Ponto(int x0, int y0)
{
	x = x0;
	y = y0;
	cout << "\nponto(int x0, int y0) " << getAsString();
}

Ponto::Ponto(const Ponto& z)
{
	x = rand() % 100;
	y = rand() % 100;
	cout << "\nponto(const Ponto& z) " << getAsString();
}

Ponto::~Ponto()
{
	cout << "~Ponto()";
}


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

	oss << " ponto x" << x << " y " << y << endl;

	return oss.str();
}

class Rectangulo //objecto composto
{
	Ponto canto;
	int largura;
	int altura;
public:
	Rectangulo(int x, int y, int largura0, int altura0);
	Rectangulo(const Ponto& p0, int largura0, int altura0);
	~Rectangulo();


	Ponto getCanto() const
	{
		return canto;
	}

	int getX()const
	{
		return canto.getX();
	}
	int getY()const
	{
		return canto.getY();
	}

	int getLargura() const
	{
		return largura;
	}

	int getAltura() const
	{
		return altura;
	}

	bool setLargura(int larg0);
	bool setAltura(int alt0);

	void setCanto(const Ponto& c);

	string getAsString() const;

	int calculaArea()const;
};

Rectangulo::Rectangulo(int x, int y, int largura0, int altura0):canto(x,y) //canto(x,y) membro objecto
{
	if(!setLargura(largura0))
	{
		largura = 1;
	}
	if (!setAltura(altura0))
	{
		altura = 1;
	}
	cout << "\nrectangulo int x, int y.." << getAsString();
}
 
Rectangulo::Rectangulo(const Ponto& p0, int largura0, int altura0):canto(p0)
{
	cout << "\nrectangulo const Ponto& p0.." << getAsString();
}

Rectangulo::~Rectangulo()
{
	cout << "~Rectangulo()" << getAsString();
}

bool Rectangulo::setLargura(int larg0)
{
	if(larg0<0) 
	{
		return false;
	}
	largura = larg0;
	return true;
}

bool Rectangulo::setAltura(int alt0)
{
	if(alt0<0)
	{
		return false;
	}
	altura = alt0;
	return true;
}

void Rectangulo::setCanto(const Ponto& c)
{
	canto = c;
}

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

	oss << " rectangulo " << canto.getAsString() << " larg: " << largura << " alt: " << altura << endl;

	return oss.str();
}

int Rectangulo::calculaArea() const
{
	return largura * altura;
}

int main()
{
	//a) relação de composição

	//b)
	//Rectangulo a(1, 2, 4, 2);
	//cout << "\na:" << a.getAsString() << endl;
	//Rectangulo b(1, 2, 44, 22);
	//cout << "\nb:" << a.getAsString() << endl;
	//os cantos são iguais, mas estão localizados em sitios diferentes de memória..
	//cada rectangulo tem a posso exclusiva do seu canto. mas são diferentes
	
	const Rectangulo c(1, 2, 4, 2);
	c.getLargura();
	
	
	cout << "\nfim do main" << endl;
	return 0;
}

………..ficha3, exercicio4 (a9, a10)

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

using namespace std;

class Ponto
{
	int x;
	int y;
public:
	//Ponto(); //construtor por omissao
	//Ponto(int x0, int y0);
	Ponto(int x0 = 0, int y0 = 0); //construtor por omissão
	Ponto(const Ponto& z);
	~Ponto();

	int getX() const
	{
		return x;
	}

	void setX(const int x)
	{
		this->x = x;
	}

	int getY() const
	{
		return y;
	}

	void setY(const int y)
	{
		this->y = y;
	}

	string getAsString() const;

	//calcular a distancia entre dois pontos
	double calculaDistancia(const Ponto& outro)const;
	bool isIgual(const Ponto& outro)const;
	
};

Ponto::Ponto(int x0, int y0)
{
	x = x0;
	y = y0;
	//cout << "\nponto(int x0, int y0) " << getAsString();
}

Ponto::Ponto(const Ponto& z)
{
	x = rand() % 100;
	y = rand() % 100;
	//cout << "\nponto(const Ponto& z) " << getAsString();
}

Ponto::~Ponto()
{
	cout << "~Ponto()";
}


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

	oss << " ponto x " << x << " y " << y << endl;

	return oss.str();
}

double Ponto::calculaDistancia(const Ponto& outro) const
{
	//pitágoras, calculo da distância
	double dist = (x - outro.x) * (x - outro.x) + (y - outro.y) * (y - outro.y);
	return sqrt(dist);
}

bool Ponto::isIgual(const Ponto& outro) const
{
	return x == outro.x && y == outro.y;
}

class Rectangulo //objecto composto
{
	Ponto canto;
	int largura;
	int altura;
public:
	Rectangulo(int x, int y, int largura0, int altura0);
	//Rectangulo(const Ponto& p0, int largura0, int altura0);
	//Rectangulo(const Rectangulo& r); //construtor por cópia
	~Rectangulo();


	Ponto getCanto() const
	{
		return canto;
	}

	int getX()const
	{
		return canto.getX();
	}
	int getY()const
	{
		return canto.getY();
	}

	int getLargura() const
	{
		return largura;
	}

	int getAltura() const
	{
		return altura;
	}

	bool setLargura(int larg0);
	bool setAltura(int alt0);

	void setCanto(const Ponto& c);

	string getAsString() const;

	int calculaArea()const;
};

Rectangulo::Rectangulo(int x, int y, int largura0, int altura0) :canto(x, y) //canto(x,y) membro objecto
{
	if (!setLargura(largura0))
	{
		largura = 1;
	}
	if (!setAltura(altura0))
	{
		altura = 1;
	}
	//cout << "\nrectangulo int x, int y.." << getAsString();
}

//Rectangulo::Rectangulo(const Rectangulo& r)
//{
//	*this = r;
//	cout << "\nRectangulo(const Rectangulo& r) " << getAsString() << endl;
//}

//Rectangulo::Rectangulo(const Ponto& p0, int largura0, int altura0) :canto(p0)
//{
//	cout << "\nrectangulo const Ponto& p0.." << getAsString();
//}

Rectangulo::~Rectangulo()
{
	cout << "~Rectangulo()" << getAsString();
}

bool Rectangulo::setLargura(int larg0)
{
	if (larg0 < 0)
	{
		return false;
	}
	largura = larg0;
	return true;
}

bool Rectangulo::setAltura(int alt0)
{
	if (alt0 < 0)
	{
		return false;
	}
	altura = alt0;
	return true;
}

void Rectangulo::setCanto(const Ponto& c)
{
	canto = c;
}

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

	oss << " rectangulo " << canto.getAsString() << " larg: " << largura << " alt: " << altura << endl;

	return oss.str();
}

int Rectangulo::calculaArea() const
{
	return largura * altura;
}

class Desenho
{
	string nome;
	vector<Rectangulo> rectangulos; //coleccão de rectangulos
	//ao ser destruido o vector são destruidos os seus elementos,
	//são destruidos os rectangulos
	//existe assim uma relação de composição
	//relação de posse exclusiva
public:
	Desenho(string nome0);
	~Desenho();

	void acrescentar(int x, int y, int alt, int larg); //um rectangulo
	int calculaAreda()const;
	vector<Rectangulo> pesquisarRectMesmoCanto(const Ponto& p)const; //const, função de consulta, e retorna o conjunto dos rect que satifazem a condição
	int somaDasAreas()const;
	int calculaArea()const;

	string getAsString() const;

	bool eliminarUm(unsigned int qual);
	int eliminarRectAreaSup(int areaLimite);
};

Desenho::Desenho(string nome0)//:nome(nome0)
{
	//ou
	nome = nome0;
	//ou
	//se nada for indicado, ele vem construido na mesma sendo usada o construtor por omissão
}

Desenho::~Desenho()
{
	cout << "\n~Desenho" << getAsString();
}

void Desenho::acrescentar(int x, int y, int larg , int alt)
{
	Rectangulo rect(x, y, larg, alt);
	rectangulos.push_back(rect); //é feito uma cópia do rect para o vector, pelo construtor por cópia
	//ou
	//rectangulos.push_back(Rectangulo(x, y, larg, alt));
}

int Desenho::calculaAreda() const
{
	return 1;
}

vector<Rectangulo> Desenho::pesquisarRectMesmoCanto(const Ponto& p) const
{
	vector<Rectangulo> v;

	for(const auto & rect : rectangulos)
	{
		//ou
		if(rect.getCanto().isIgual(p))
		{
			v.push_back(rect);
		}
		//ou, mas falha o encapsulamento
		//pois é a classe do ponto que sabe se dois pontos são iguais
		//pois quem deve ter a funcionalidade é a classe que tem a informação correspondente
		//assim não deve ser a classe desenho a faze-lo
		//if(rect.getCanto().getX() == p.getX() && rect.getCanto().getY() == p.getY())
		//{
		//	v.push_back(rect);
		//}
	}
	return v;
}

int Desenho::somaDasAreas() const
{
	int soma = 0;
	//ou
	for(vector<Rectangulo>::const_iterator it = rectangulos.begin(); it != rectangulos.end(); ++it)
	{
		soma += it->calculaArea();
	}
	//ou
	for(auto it = rectangulos.begin(); it != rectangulos.end(); ++it)
	{
		soma += it->calculaArea();
	}
	//ou
	for(unsigned int i= 0; i< rectangulos.size(); i++)
	{
		soma += rectangulos[i].calculaArea();
	}
	
	//ou
	for(const auto & elem:rectangulos)
	{
		soma += elem.calculaArea();
	}
	

	return soma;
}

int Desenho::calculaArea() const
{
	int area = 0;
	return area;
}

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

	oss << " nome " << nome << " tem " << rectangulos.size() << " rectangulos \n ";

	//ou
	for(unsigned int i = 0; i< rectangulos.size(); i++){
		oss << rectangulos[i].getAsString() << endl;
	}
	//ou
	//for( auto & rect : rectangulos)
	//{
	//	oss << rect.getAsString() << endl;;
	//}
	//ou iteradores
	//for(vector<Rectangulo>::const_iterator it =rectangulos.begin(); it != rectangulos.end(); ++it)
	//{
	//	oss << it->getAsString() << endl;
	//}
	return oss.str();
}

bool Desenho::eliminarUm(unsigned qual) //qual: indice
{
	{
		if (qual < 0 || qual >= rectangulos.size())
		{
			return false;
		}
		rectangulos.erase(rectangulos.begin() + qual); //o vector auto-reorganiza-se
		//é um iterator: rectangulos.begin() + qual
		return true;
	}
}

int Desenho::eliminarRectAreaSup(int areaLimite)
{
	//serve para coleções
	//https://www.cplusplus.com/reference/vector/vector/erase/
	int nEliminar = 0;
	for(vector<Rectangulo>::iterator it = rectangulos.begin(); it != rectangulos.end();)
	{
		if(it->calculaArea() > areaLimite)
		{
			it = rectangulos.erase(it);
			++nEliminar;
		}else
		{
			++it;
		}
	}
	return nEliminar; //não era necessaria esta informação
}

int main()
{
	Desenho a1("janela");
	cout << "\na1";
	a1.acrescentar(1, 2, 3, 4);
	a1.acrescentar(5, 6, 7, 8);
	a1.getAsString();
	
	cout << "\nfim do main.." << endl;
	return 0;
}

………..ficha3, exercicio7 (a11, a12)

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

using namespace std;

//relação entre banco, conta, pessoa e arquivo de identificacao:
//relação entre banco e conta: composição (banco cria a conta)
//quando o banco for destruído as contas tambem o são
//relação entre conta e pessoa: agregação
//relação entre arquivo de identificacao e pessoa: composição (arquivo cria a pessoa)

class Pessoa
{
	//objecto dinamico, que não muda.
	string nome;
	long bi;
	long nif;

	void setBi(long bi); //alteração é privado
public:
	Pessoa(const string& s, long b, long n);
	Pessoa() = delete; //não disponbilizamos construtor por omissão, fica proibido
	~Pessoa();

	string getNome() const;
	void setNome(const string& nome);

	long getBi() const;
	
	long getNif() const;
	void setNif(const long nif);
	
	string getAsString()const;
	string getDados()const;
};

Pessoa::~Pessoa()
{
	cout << "~Pessoa()" << endl;
}

string Pessoa::getNome() const
{
	return nome;
}

void Pessoa::setNome(const string& nome)
{
	this->nome = nome;
}

long Pessoa::getBi() const
{
	return bi;
}

void Pessoa::setBi(const long bi)
{
	this->bi = bi;
}

Pessoa::Pessoa(const string& s, long b, long n):nome(s), bi(b),nif(n)
{
}

long Pessoa::getNif() const
{
	return nif;
}

void Pessoa::setNif(const long nif)
{
	this->nif = nif;
}

string Pessoa::getAsString() const
{
	ostringstream oss;
	oss << "nome: " << nome << " bi: " << bi << " nif: " << nif << endl;
	
	return oss.str();
}

string Pessoa::getDados() const
{
	//ficheiro de dados, linha
	ostringstream oss;
	oss << bi << " " << nif << nome << endl;

	return oss.str();
}

class ArquivoDeIdentificacao
{
	//vector de ponteiros para pessoas
	//ou vector de pessoas/objectos (não ia funcionar bem, porque na conta existe um ponteiro para pessoa, e se for eliminado no arquivo o ponteiro fica como?)
	//o destrutor tem que destruir primeiro as pessoas, libertar a memória com delete
	string nome;
	vector<Pessoa* > pessoas;
	int pesquisa(long bi)const;
public:
	ArquivoDeIdentificacao(string nome0);
	ArquivoDeIdentificacao(const ArquivoDeIdentificacao& ob) = delete; //proibir a construção por cópia
	ArquivoDeIdentificacao& operator=(const ArquivoDeIdentificacao& ob) = delete; //proibir o operador atribuição, proibir a atribuição
	//esta dupla proibição tem a ver com evitar erros de execuação
	~ArquivoDeIdentificacao();

	string getNome() const;
	void setNome(const string& nome);
	bool acrescentaPessoa(string n, long b, long nif); //relação de posse o arquivo.
	string getDados()const; //para lidar com ficheiros
	const Pessoa * getPessoa(long bi);
	
	string getAstring()const;

	bool gravarPessoasEmFicheiroDeTexto(const ArquivoDeIdentificacao &arquivo);
	bool lerPessoasDeFicheiroDeTexto(ArquivoDeIdentificacao &arquivo);
};


int ArquivoDeIdentificacao::pesquisa(long bi) const
{
	//porque existe uma coleção
	for(unsigned int i = 0; i< pessoas.size(); i++)
	{
		if(pessoas[i]->getBi()==bi)
		{
			return i;
		}
	}
	return -1;
}

ArquivoDeIdentificacao::ArquivoDeIdentificacao(string nome0):nome(nome0)
{
}

ArquivoDeIdentificacao::~ArquivoDeIdentificacao()
{
	//o arquivo tem uma relação de composição: cria e destoi a pessoa
	for(Pessoa * p: pessoas)
	{
		cout << p->getAsString();
		delete p;
	}
	//ou
	//for (int i = 0; i < pessoas.size(); i++)
	//	delete pessoas[i];
}

string ArquivoDeIdentificacao::getNome() const
{
	return nome;
}

void ArquivoDeIdentificacao::setNome(const string& nome)
{
	this->nome = nome;
}

bool ArquivoDeIdentificacao::acrescentaPessoa(string n, long b, long nif)
{
	int qual = pesquisa(b);
	if(qual != -1)
	{
		return false; //já existe uma pessoa com este bi
	}
	pessoas.push_back(new Pessoa(n, b, nif));
	//o arquivo tem uma relação de composição: cria e destoi a pessoa
	//new Pessoa(n, b, nif)  //criar a pessoa em memória dinamica, e retorna o endereço
	//pessoas.push_back //acrescenta mais um elemento com o endereço da nova pessoa
	return true; 
}

string ArquivoDeIdentificacao::getDados() const
{
	//para lidar com ficheiros
	ostringstream oss;
	for(Pessoa * p: pessoas)
	{
		oss << p->getDados() << endl;
	}

	return oss.str();
}

const Pessoa* ArquivoDeIdentificacao::getPessoa(long bi)
//primeiro const: para nao alterar o ponteiro, damos acesso apenas aos dados para onde aponta (read only)
{
	int qual = pesquisa(bi);
	if(qual == -1)
	{
		return nullptr;
	}else
	{
		return pessoas[qual];
	}
}

string ArquivoDeIdentificacao::getAstring() const
{

	ostringstream oss;
	for(Pessoa * p : pessoas)
	{
		oss << p->getAsString();
	}
	return oss.str();
}

bool ArquivoDeIdentificacao::gravarPessoasEmFicheiroDeTexto(const ArquivoDeIdentificacao & arquivo)
{
	ofstream dados("dados.txt");
	if (!dados.is_open()) {
		return false;
	}

	dados << arquivo.getDados();

	dados.close();
	if (dados) {
		return true;
	}
	else return false;
}

bool ArquivoDeIdentificacao::lerPessoasDeFicheiroDeTexto(ArquivoDeIdentificacao& arquivo)
{
	ifstream dados("dados.txt");
	string nome;
	long bi;
	long nif;
	string s;

	if (!dados.is_open()) {
		return false;
	}

	// ler dados de todas as pessoas
	// uma por linha

	while (!dados.eof()) {
		// ler strig com os dados da pessoa
		getline(dados, s);

		istringstream iss(s);
		// ler dados da pessoa
		iss >> bi >> nif;
		getline(iss, nome);

		// se correu bem a leitura ...
		if (iss) {
			acrescentaPessoa(nome, bi, nif);
		}
	}
	dados.close();
	return true;
}

class Conta
{
	//ponteiro para pessoa
	const Pessoa* titular; //const, para não alterar 
	int saldo;
public:
	Conta(const Pessoa* const titular); //posso usar um ponteiro para const ou sem const
	//ou
	//Conta(Pessoa* const titular); //pode alterar o apontado desta forma
	~Conta();

	const Pessoa* getTitular()const; //não altera, damos o conhecimento

	int getSaldo()const;
	bool depositar(int quantia);
	bool levantar(int quantida);

	long getBi()const;

	string getAsString()const;

};

Conta::Conta(const Pessoa* const titular):titular(titular), saldo(0)
{
}

Conta::~Conta()
{
	cout << "~Conta()" << endl;
}

const Pessoa* Conta::getTitular() const
{
	return titular;
}

int Conta::getSaldo() const
{
	return saldo;
}

bool Conta::depositar(int quantia)
{
	if (quantia <= 0)
		return false;
	saldo += quantia;
	return true;
}

bool Conta::levantar(int quantia)
{
	if (quantia <= 0 || quantia > saldo)
		return false;
	saldo -= quantia;
	return true;
}

long Conta::getBi() const
{
	return titular->getBi();
}

string Conta::getAsString() const
{
	ostringstream oss;
	oss << "\ntitular " << titular->getAsString() << "\nsaldo " << saldo << endl;
	return oss.str();
}

class Banco
{
	string nome;
	//vector de objectos contas
	vector <Conta> contas;
	//a destruição deste obejcto vai destruir os membros de outras classes: vector e nome

	int pesquisar(long bi)const;
public:
	Banco(string n);
	//~Banco(); //não é preciso, porque as contas não sobrevivem ao fim do banco

	string getNome() const;
	void setNome(const string& nome);
	bool acrescentar(const Pessoa* const pessoa);
	bool eliminar(long bi);
	int somaDosSaldos()const;
	bool depositar(long bi, int quantia);
	bool levantar(long bi, int quantia);

	void eliminarTodasAsContas(long bi);

	
	string getAsString()const;
	
};

int Banco::pesquisar(long bi) const
{
	for(unsigned int i=0; i< contas.size(); i++)
	{
		if(bi == contas[i].getBi())
		{
			return i;
		}
	}
	return -1;
}

Banco::Banco(string n):nome(n) //vai funcionar o construtor por omissão, e fica vazio, sem lixo/elementos
{
}

//Banco::~Banco()
//{
//	cout << "\n~Banco" << endl;
//}

string Banco::getNome() const
{
	return nome;
}

void Banco::setNome(const string& nome)
{
	this->nome = nome;
}

bool Banco::acrescentar(const Pessoa* const pessoa)
{
	if (pessoa == nullptr){
		return false;
	}
	contas.push_back(Conta(pessoa)); //criar contas, é o banco que o faz
	return true;
}

bool Banco::eliminar(long bi)
{
	int qual = pesquisar(bi);
	if(qual == -1)
	{
		return false;
	}
	contas.erase(contas.begin() + qual);
	return true;
}

int Banco::somaDosSaldos() const
{
	int soma = 0;
	for(const Conta &c : contas)
	{
		soma += c.getSaldo();
	}
	return soma;
}

bool Banco::depositar(long bi, int quantia)
{
	int qual = pesquisar(bi);
	if(qual == -1)
	{
		return false;
	}
	return contas[qual].depositar(quantia);
}

bool Banco::levantar(long bi, int quantia)
{
	int qual = pesquisar(bi);
	if(qual == -1)
	{
		return  false;
	}
	return contas[qual].levantar(quantia);
}

void Banco::eliminarTodasAsContas(long bi) //vector
{
	{
		for (auto it = contas.begin(); it != contas.end();)
		{
			if (it->getBi() == bi)
			{
				it = contas.erase(it);
			}
			else
			{
				++it;
			}
		}
	}
}

string Banco::getAsString() const
{
	ostringstream oss;
	oss << "\n== Banco : " << nome << "\t n.contas " << contas.size() << endl;

	for (unsigned int i = 0; i < contas.size(); i++)
	{
		oss << contas[i].getAsString();
	}
	
	return oss.str();
}

int main()
{
	//Pessoa p("coimbra", 123, 321);
	//cout << p.getAsString();

	//Pessoa* ap=nullptr;
	//ou
	//Pessoa* const ap = nullptr; //preciso que Conta(const Pessoa* const titular); 
	//ou
	//const Pessoa* const ap=nullptr; //preciso que Conta(const Pessoa* const titular); 
	//Conta c1(ap);

	/*Pessoa p1("AAA", 123, 321);
	Pessoa p2("BBB", 928, 890);
	Banco b("o banco b");
	b.acrescentar(&p1);
	b.acrescentar(&p2);

	cout << "Banco \n" << b.getAsString() << endl;

	b.depositar(123, 40);
	b.depositar(928, 240);

	cout << "Bancos depositos\n" << b.getAsString() << endl;*/

	//ArquivoDeIdentificacao arquivo("coimbra");
	//ArquivoDeIdentificacao arquivo2("porto");
	//ArquivoDeIdentificacao arquivo3(arquivo2); //dá erro, proibida a cópia de arquivo2, construção por cópia
	//arquivo1 = arquivo2; //dá erro, poribida a atribuição , atribuição

	//arquivo.acrescentaPessoa("pedro", 123, 456);
	//arquivo.acrescentaPessoa("ines", 888, 999);
	//	
	//cout << "arquivo de identificacao\n" << arquivo.getAstring();
	

	//ArquivoDeIdentificacao arquivo("coimbra final");
	//arquivo.acrescentaPessoa("pedro", 123, 456);
	//arquivo.acrescentaPessoa("ines", 888, 999);

	//cout << "arquivo de identificacao\n" << arquivo.getAstring();
	//
	//Banco banco("filial coimbra");
	//banco.acrescentar(arquivo.getPessoa(123));
	//banco.acrescentar(arquivo.getPessoa(888));
	//banco.acrescentar(arquivo.getPessoa(88));
	//banco.acrescentar(arquivo.getPessoa(123));

	//cout << "banco" << banco.getAsString() << endl;

	
	//operação grava ficheiro
	//ArquivoDeIdentificacao arquivo("coimbra");
	//arquivo.acrescentaPessoa("pedro", 123, 456);
	//arquivo.acrescentaPessoa("ines", 888, 999);
	//cout << "arquivo de identificacao\n" << arquivo.getAstring();
	//Banco banco("filial coimbra");
	//banco.acrescentar(arquivo.getPessoa(123));
	//banco.acrescentar(arquivo.getPessoa(888));
	//banco.acrescentar(arquivo.getPessoa(88));
	//banco.acrescentar(arquivo.getPessoa(123));

	//cout << "banco" << banco.getAsString() << endl;
	//arquivo.gravarPessoasEmFicheiroDeTexto(arquivo);

	
	//operação ler ficheiro
	//ArquivoDeIdentificacao arquivo2("porto final");
	//arquivo2.lerPessoasDeFicheiroDeTexto(arquivo2);
	//
	//cout << "arquivo de identificacao\n" << arquivo2.getAstring();
	//Banco banco("filial coimbra");
	//banco.acrescentar(arquivo2.getPessoa(123));
	//banco.acrescentar(arquivo2.getPessoa(888));
	//banco.acrescentar(arquivo2.getPessoa(88));
	//banco.acrescentar(arquivo2.getPessoa(123));

	//cout << "banco" << banco.getAsString() << endl;

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

Encapsulamento, classes, construtores, destrutores

………..ficha2, exercicio3e4 (a4,a5)

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

………..ficha2, exercicio5 (a5)

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

using namespace std;

class Automovel
{
private:
	string matricula;
	string combustivel;
	string marca;
	string modelo;
	int ano;
	static int conta; //não surge nos objectos, surge fora dos objectos, membro estático
	//e vai precisar de ser inicializado, no inicio e surge int Automovel::conta = 0;

	//validar a matricula do automovel
	bool validaMatricula(const string & s) const ;

public:
	Automovel(const string& matricula, const string& combustivel, const string& marca, const string& modelo,
		const int ano)
		: combustivel(combustivel),
		  marca(marca),
		  modelo(modelo) //o ano nao surge aqui fica com lixo
	{
		setMatricula(matricula); //construida por omissão
		setAno(ano); //construida por omissão 
		++conta;
	}

	string getMatricula() const
	{
		return matricula;
	}
	string getCombustivel() const
	{
		return combustivel;
	}
	string getMarca() const
	{
		return marca;
	}
	string getModelo() const
	{
		return modelo;
	}
	int getAno() const
	{
		return ano;
	}
	static int getConta();

	
	void setMatricula(const string & matricula)
	{
		if(validaMatricula(matricula)){
			this->matricula = matricula;
		}
		//this->matricula = "99-AA-99";
	}
	void setCombustivel(const string& combustivel)
	{
		this->combustivel = combustivel;
	}
	void setMarca(const string& marca)
	{
		this->marca = marca;
	}
	void setModelo(const string& modelo)
	{
		this->modelo = modelo;
	}
	void setAno(const int ano)
	{
		if (ano > 2000 && ano < 2021) {
			this->ano = ano;
		}
		else {
			this->ano = 0;
		}
	}
	string getAsString()const;
};

int Automovel::conta = 0; //vai ser criado logo no inicio do main

int Automovel::getConta()
{
	return  conta;
}

string Automovel::getAsString()const
{
	ostringstream oss;
	oss << "\nmatricula: " << matricula
		<< "\ncombustivel: " << combustivel
		<< "\nmarca: " << marca
		<< "n\\nmodelo: " << modelo
		<< "\nano: " << ano;
	return oss.str();
}
bool Automovel::validaMatricula(const string & s) const
{
	//v1
	//if (s.length() != 8)
	//{
	//	return false;
	//}
	//return true;
	//v2 expressões regulares
	string patern = "((\d{2}-\d{2}-[A-Z]{2}) | (\d{2}-[A-Z]{2}-\d{2}) | (\[A-Z]{2}-\d{2}-\d{2}))";
	//string patern = R"((\d{2}-\d{2}-[A-Z]{2}) | (\d{2}-[A-Z]{2}-\d{2}) | (\[A-Z]{2}-\d{2}-\d{2}))";
	//string patern = R"(([A-Z]{2}-\d{2}-(\d{2}|[A-Z]{2}))|(\d{2}-(\d{2}-[A-Z]{2}|[A-Z]{2}-\d{2})))";
	regex reg(patern);
	if(regex_match(s, reg))
	{
		return true;
	}
	return false;
}
int main()
{
	cout << "\nconta: " << Automovel::getConta() << endl;
	
	Automovel A1("11-22-CD", "gasolina", "opel", "corsa", 2020);
	
	cout << A1.getAsString();
	cout << "\nconta: " << Automovel::getConta() << endl;
	
	cout << "\nfim da main";
	return 0;
}

………..ficha2, exercicio7 (a6,a7)

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

using namespace std;

class MSG
{
private:
	char letra;
	int numero;
	static int contador;

	//MSG(const MSG& ob); //i)
	
public:
	MSG(char letra = 'X'); //por valor por omissão, um constutor por omissão
	//MSG(char letra); //alternativa que tb funcionar a aliena e)
	~MSG();
	//construtor por cópia
	MSG(const MSG& ob);

	char getLetra() const
	{
		return letra;
	}

	void setLetra(const char letra)
	{
		this->letra = letra;
	}
	int getNumero() const
	{
		return numero;
	}

	void setNumero(const int numero)
	{
		this->numero = contador;
	}
	string getAsString() const;
};

int MSG::contador = 0;

MSG::MSG(char letra)
{
	this->letra = letra;
	this->numero = ++contador;
	cout << "\ncriado: " << getAsString() << endl;
}

MSG::~MSG()
{
	cout << "\nterminado: "<< getAsString() << endl;
}

//construtor por cópia c)
MSG::MSG(const MSG& ob)
{
	//anular o construtor por cópia por defeito que é fornecido pelo compilador
	letra = ob.letra;
	numero = -ob.numero; //para fazer uma coisa diferente (numero simétrico)
	cout << "\nCriado por copia " << getAsString();
}

string MSG::getAsString() const
{
	ostringstream oss;
	oss << "\nletra " << getLetra() << " numero " << getNumero() << endl;
	
	return oss.str();
}

void teste_g()
{
	MSG aux('y');
}

void teste_h(MSG z)
{
	//h)
	//a passagem de um objecto como parametro por valor (funcionou o construtor por cópia)
	//(z é copia de b, e funciona o construtor por cópia)
}

void teste_l(MSG & z) //passar o objecto por referencia
{
	//l)
	//uma referencia não tem o seu lugar proprpio, vai ser apenas outro nome para b,
	//z coincide em memoria com b, não surge outro objecto, é apenas outro nome
	//constutor e destrutor são os mesmos
}

MSG  teste_m()
{
	MSG m; //é criado localemnte um objecto m
	return m; //retornar o m por valor
}

MSG & teste_n() //retorno por referencia, para uma variavel que já existe
{
	MSG m; //é criado localemnte um objecto m
	return m; //retornar o m com estatuto de referencia ( não existe uma cópia )
}

int main()
{
	//objectos não dinamicos, que vai ser destruido no fim do main
	//MSG m1('a');
	//MSG m2; //para fazer uso do default

	//objectos dinâmicos
	//MSG* p = new MSG('D');
	//cout << "\n vou construir D";
	//delete p; //destruo o objecto apontado por p, destruido expressamente
	//cout << "\n vou destruir D";

	//MSG & m3 = m2; //alinea b)
	//m3 é uma referência que se vai "colar" a m2, m3 é um outro nome para m2
	//não vai ser criado mais nenhum objecto

	//c)
	//MSG m4 = m2;
	//não existe nenhum construtor por cópia implementado
	//mas funionou um
	//todas as classe que não tenham um construtor por cópia, o compilador fornece um
	//a nossa construção do construtor por cópia
	//MSG m4 = m2; //criado por cópia

	//d) atribuição
	//MSG m4 = m2; //criado por cópia
	//m1 = m2; //atribuição

	//e) matriz (array) de objectos
	//MSG mat1[] = {'M', 'N'};

	//f) matriz (array) de objectos
	//MSG mat2[2]; //criado se e só existir um constutor por omissão
	//ou
	//MSG m1('a');
	//MSG m2; //para fazer uso do default
	//MSG mat[] = { m1, m2 };
	//ou
	//MSG mat[4] = { MSG('A') , MSG('B') };
	//ou
	//MSG mat[4] = { MSG() , MSG() };

	//g)
	/*cout << "\n alinea g)" << endl;
	teste_g();
	cout << "\n alinea g)" << endl;
	teste_g();*/

	//h)
	//MSG b;
	//cout << "\n alinea h)" << endl;
	//teste_h(b);
	//cout << "\n alinea h)" << endl;
	//teste_h(MSG('c'));
	//a passagem de um objecto como parametro por valor (funcionou o construtor por cópia)
	//(z é copia de b, e funciona o construtor por cópia)

	//i) e j)
	//em privado o  construtor po cópia MSG(const MSG & ob);
	//mas sendo privado a cópia não vai funcionar, teste_h(b);

	//k)
	//objecto é criado com lixo, e é bloqueada a construção por cópia do compilador
	
	
	//l)
	/*MSG b;
	teste_l(b);*/

	//m)
	//MSG b = teste_m(); //o valor m chegou aqui
	//, mas m perde a validade no primeiro }, morre aqui, é terminado
	//vai ser feita uma copia de m e é este que vai representar a informação a seguir ao = do teste_m()
	//quem actua é o construtor por cópia, o return é uma cópia

	//n) retorno por referência
	MSG b = teste_n(); //
	
	
	cout << "\nfim do main" << endl;
	return 0;
}

………..ficha2, exercicio9 (a7, a8)

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

using namespace std;

class Televisao
{
	vector<string> canais; //estes endereços podem mudar de sítio
	//acrescentar elementos ao canais.push_back("rtp1");
	//string s = "sic";
	//canais.push_back(s);
	//percorrer:
	//for(int i = 0; i< canais.size(); i++){
	// cout << canais[i];
	//}
	//esvaziar tudo:
	//canais.clear(); //size a zero
	//alternativa será uso de vectores de ponteiros para objectos dinâmicos (dinâmicos vão estar no seu lugar)
	
	bool ligada;
	int volume;
	int canal; //indice do vector de canais +1
	string nomeCanal;

	//o conjunto de canais definido na construção não se altera a partir do exterior da classe
	void setCanais(string canais0[], unsigned int n);

public:
	Televisao(string canais0[], int n);

	bool isLigada()const; //is por ser booleana
	void ligar();
	void desligar();

	void aumentaVolume();
	void diminuiVolume();

	void mudaCanal(int c);
				
	int getCanal() const
	{
		return canal;
	}

	//para experimentar
	Televisao(initializer_list<string> canais0); //lista de constantes, separadas por virgulas e chavetas
	void setCanais(initializer_list<string> canais0);
	void setCanais2(vector<string> canais0); 
		
	string getAsString()const;
		
};

void Televisao::setCanais(string canais0[], unsigned int n)
{
	//validação
	if(n< 0)
	{
		n = 0;
	}
	//se já tiver previamente preecnhido
	canais.clear();
	for(unsigned int i = 0; i < n; ++i)
	{
		canais.push_back(canais0[i]); //copiar os elementos para o vector de strings
	}
}

Televisao::Televisao(string canais0[], int n)
{
	setCanais(canais0, n);
	ligada = false;
	volume = 0;
	canal = 1;
	cout << "\nNormal" << endl;
}

bool Televisao::isLigada() const
{
	return ligada;
}

void Televisao::ligar()
{
	ligada = true;
}

void Televisao::desligar()
{
	ligada = false;
}

void Televisao::aumentaVolume()
{
	if (ligada != true)
		return;
	if (volume <= 10)
		volume++;
}

void Televisao::diminuiVolume()
{
	if (ligada != true) 
		return;
	if (volume >= 10)
		volume--;
}

void Televisao::mudaCanal(int c)
{
	if (ligada != true)
		return;
	unsigned cc = c;
	if (cc > 0 && cc <= canais.size())
		canal = c;
}

Televisao::Televisao(initializer_list<string> canais0)
{
	setCanais(canais0);
	ligada = false;
	volume = 0;
	canal = 1;
	cout << "\nInitializer" << endl;
}

void Televisao::setCanais(initializer_list<string> canais0)
{
	canais.clear();
	//ou
	//for (const auto& c : canais)
	//{
	//	canais.push_back(c);
	//}
	//ou
	//for (initializer_list<string>::iterator it = canais0.begin(); it != canais0.end(); ++it){
	//	canais.push_back(*it);
	//}
	//ou
	for(auto it = canais0.begin(); it != canais0.end(); ++it)
	{
		canais.push_back(*it);
	}
}

void Televisao::setCanais2(vector<string> canais0)
{
	canais.clear();
	for (auto it = canais0.begin(); it != canais0.end(); ++it)
	{
		canais.push_back(*it);
	}
}

string Televisao::getAsString() const
{
	ostringstream oss;
	
	//for(unsigned int i = 0; i < canais.size() ; ++i)
	//{
	//	//oss << canais[i] << " ";
	//	oss << canais.at(i) << " ";
	//}

	//for (const string& c : canais) //c é um outro nome para cada um dos elementos da coleção
	//	oss << c << " ";

	//for (string c : canais) //c é uma copia dos elementos da coleção
	//	oss << c << " ";

	//for (const auto & c : canais)
	//	oss << c << " ";

	//iterador aponta para os elementos do objecto e desta forma conseguimos percorrer
	//for (vector<string>::const_iterator it = canais.begin(); it != canais.end(); ++it)
	//	oss << *it << " ";

	for( auto it = canais.begin() ; it != canais.end(); ++it)
	{
		oss << *it << " ";
	}

	if(!ligada)
	{
		oss << "desligada\n";
		return oss.str();
	}
	if(canais.empty())
	{
		oss << "sem canais ";
		return oss.str();
	}
	
	oss << "\nCanal"  << canais[canal-1] << " " << canal << "\nvolume: " << volume << endl;

	return oss.str();
}

int main()
{
	//exemplos dos inicializer lists
	Televisao tv = { "um","dois","tres","quatro" };
	Televisao tv2{ "um", "dois" };
	Televisao tv3({ "um","dois" });
	//outro exemplo e se for construtor e fizer uso dos ()
	tv.setCanais2({ "um","dois","tres" });

	//uniform inicialization
	//usar estes construtor Televisao(string canais0[], int n);
	string canais[] = { "um","dois" };
	Televisao tv4(canais, 2);
	Televisao tv5{ canais, 2 };
	Televisao tv6 = { canais, 2 };
	
	cout << "\nfim do main" << endl;
	return 0;
}

………..ficha2, exercicio5 (a10, a11)

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

using namespace std;

class Prego {
	int x, y;
public:
	Prego(int a, int b);
	~Prego();
	void mudaDeSitio(int a, int b);

	string getAsString() const;

	int getX()const { return x; }
	int getY()const { return y; }
};

Prego::Prego(int a, int b):x(a), y(b)
{
	//x = a; y = b;
	cout << "construindo prego em " << x << "," << y << "\n";
}

Prego::~Prego()
{
	cout << "~Prego em " << x << "," << y << "\n";
}

void Prego::mudaDeSitio(int a, int b)
{
	x = a; y = b;
}

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

	oss << "Prego: ( " << x << " , " << y << " ) ";
	
	return oss.str();
}

class Aviso
{
	string texto;
	//Prego prego; //relação de composição.
	//Prego * prego;
	//usamos um ponteiro, já não é uma posse exclusiva
	//aviso é destruído, o prego fica lá..
	//com ponteiro pode haver posse excluiva ou não
	//Prego * const prego;
	//não é possivel mudar o endereço do prego
	//recebe um valor e não pode mudar, usa-se o const
	const Prego * const prego;
	//O aviso nao te direito a fazer alterações ao Prego... const Prego
	//a relação entre aviso e prego é de agregação (tem o conhecimento)
	//porque se o aviso for destruido o prego não é
	//o prego pode ser partilhado por mais de um aviso
	//o prego já existe antes do aviso
	//o aviso tem o conhecimento do prego
public:
	Aviso(const string & t, const Prego * const p);
	~Aviso();
	int getX() const;
	int getY() const;
	string getAsString() const;
	Aviso(const Aviso& ob); //construtor por cópia
};

Aviso::Aviso(const string& t, const Prego * const p):texto(t), prego(p)
{
	//prego = p
	//nao é possivel usar porque o Prego é um membro constante de Aviso (ou até podia ser uma referencia)
	//logo tem que ser usada a outra opção
	//os membros const e os membros referencias é obrigatório inicializar na lista de inicialização do construtor
	cout << " construido Aviso " << texto << endl;
}

Aviso::~Aviso()
{
	cout << " ~Aviso() " << texto << endl;
}

int Aviso::getX() const
{
	return prego->getX();
}

int Aviso::getY() const
{
	return prego->getY();
}

string Aviso::getAsString() const
{
	ostringstream oss;
	oss << "Aviso: " << texto << " " << prego->getAsString();
	
	return oss.str();
}

Aviso::Aviso(const Aviso& ob):prego(ob.prego)
{
	texto = ob.texto+"Copia";
	cout << "CCopia de aviso " << texto << endl;
}


int main()
{
	Prego p(1, 2);
	Aviso a("quadro 1", &p);
	Aviso b("quadro 2", &p);

	cout << " A " << a.getAsString() << endl;
	cout << " B " << b.getAsString() << endl;

	p.mudaDeSitio(99, 99);

	cout << " A " << a.getAsString() << endl;
	cout << " B " << b.getAsString() << endl;

	//a=b; //erro
	//a atribuição entre dois objectos é feita membro a membro
	//o texto consegue atribuir, mas o prego pk tem const não consegue
	//assim a atribuição default dá erro, podemos é usar uma atribuição que funcione
	//usando o operador atribuição

	Aviso c = a;
	cout << " C " << c.getAsString() << endl;

	vector<Aviso> avisos;
	cout << "-pushback-\n";
	
	avisos.push_back(a);
	Aviso* pa = &avisos[0]; //ponteiro para o primeiro elemento do vector
	cout << pa->getAsString() << endl;

	avisos.push_back(b);
	Aviso* pb = &avisos[0];
	cout << pb->getAsString() << endl;

	if(pa==pb)
	{
		cout << " == \n";
	}else
	{
		cout << " != \n";
	}
	cout << avisos[0].getAsString() << endl;

	//avisos.erase(avisos.begin() + 1);
	//dá erro, pk os objectos do vector têm um membro constante
	//a atribuição dá erro, e o erase precisa de atribuições internamente
		
	cout << "\nfim do main" << endl;
	return 0;
}
Tags : , , , ,