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
0 thoughts on “objetos dinâmicos, matrizes dinâmicas, classes com construtores por cópia, operador de atribuição e destrutor”