Tag: poo_lab_pt1
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 : apontamentos, c++11, Learn C plus plus, poo_lab_pt1, poof