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