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

0 thoughts on “Encapsulamento, classes, construtores, destrutores”

Leave a Reply

Your email address will not be published.

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