Page 1 of 1

Legaturi_intre_clase

Posted: 25 Jan 2014, 20:52
by IVANA_27
Am o clasa numita PolitaAsigurare, si una numita CompanieAsigurari .
In cea de-a 2-a clasa trebuie sa am o lista de pointeri la obiecte din prima clasa mentionata.

class companieasigurari
{
int nrpolite;
politaasigurare** polite;
...
};


Vreau sa supraincarc operatorul += in clasa companieAsigurari ca sa pot adauga o noua polita. Am incercat mai multe chestii, dar de fiecare data ma blochez la cate ceva.

companieasigurari operator+=(politaasigurare* p)
{
companieasigurari c;
c.nrpolite=this->nrpolite;
c.polite=new politaasigurare*[this->nrpolite];
for(int i=0;i<c.nrpolite;i++)
{
// stiu ca trebuie sa aloc spatiu pentru fiecare polita in parte, dar nu stiu exact cum
c.polite=this->polite;
}
c.polite[c.nrpolite-1]=p;
}

Daca m-ar putea ajuta cineva as fi recunoscator. Multumesc!

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 01:19
by Silviu Ardelean
Primul hint pe care ti-l dau e sa inlocuiesti matricea de polite. Gandeste-te la cazul real: compania de asigurari poate emite oricat de multe polite de asigurare iar matricea ta polite in momentul creearii are nevoie sa stie dimensiunea sa finala pentru a stii cat aloci. Altfel, daca aloci prea mult s-ar putea sa consumi memorie inutil. Daca aloci prea putin si ai multe polite vei ajunge sa corupi heapul cand depasesti limita de polite alocate.

Recomandarea ar fi sa treci pe un container ce-ti permite cresterea dinamica de genul std::vector< std::unique_ptr<PolitaAsigurare> >. Iar atunci, pe operatorul tau += ar trebui sa faca doar un push_back() in vectorul tau polite (daca folosesti std::unique_ptr in loc de pointer normal, nu uita de std::move() ca "schimbi" ownershipul).

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 09:55
by Ovidiu Cucu
@Silviu: dar daca omu n-are std::unique_ptr in STL-ul din dotare, sau nu vrea sau nu stie ce-i aia STL sau boost, sau pur si simplu nu asta-i cere profu, ce ne facem?

@IVANA_27: de ce companieasigurari::polite trebuie sa fie de tipul politaasigurare** (ponter la pointer la politaasigurare)?

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 13:15
by IVANA_27
@IVANA_27: de ce companieasigurari::polite trebuie sa fie de tipul politaasigurare** (ponter la pointer la politaasigurare)?[/quote]

Am mai gandit putin problema. Defapt nu trebuie sa fie pointer la pointer, trebuie sa fie pointer la adresa la care se afla obiectele de tip politaasigurare. Inca sunt la nivelul la care trebuie sa ma obisnuiesc cu pointerii.
Iar eu cand supraincarc operatorul +=, va trebui ca in lista de polite sa imi adauge adresa zonei de memorie unde se afla obiectul pe care vreau sa il adaug (nu sunt sigur, dar asa mi s-ar parea logic.Nu vad rostul ca acelasi obiect sa ocupe de 2 ori memorie). Astfel ca, in main, va trebui sa fie posibila o operatie de genul :

companieasigurari* c=new companieasigurari();
c+=&p;
,unde p e un obiect de tipul politaasigurare

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 13:55
by Silviu Ardelean
Ovidiu Cucu wrote:@Silviu: dar daca omu n-are std::unique_ptr in STL-ul din dotare, sau nu vrea sau nu stie ce-i aia STL sau boost, sau pur si simplu nu asta-i cere profu, ce ne facem?
Pai ce sa ne facem... :) Fara STL poate folosi un array clasic de polite. Dar cu array-ul se poate lovi de problemele ce spuneam mai sus. Daca e doar o tema de laborator poate se accepta daca mentioneaza inconvenientele implementarii.
Altfel, se apuca si-si imlementeaza o lista (nu e optima) ori alta structura dinamica pentru a-si tine politele ( ideal un hashtable avand key-ul nr. politei :ugeek: ). Iar atunci, cu operatorul sau += va face o inserare de polita.
Mai simplu fara containere, dar tot neperformant pentru multe obiecte, e sa tina un pointer la urmatoarea polita, pointer ce-l seteaza de fiecare data cand adauga ceva pe operatorul sau.

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 14:25
by Viorel
Dacă nu dorești să simplifici, atunci încearcă asta:

Code: Select all

companieasigurari operator += ( politaasigurare* p )
{
    companieasigurari c;
    c.nrpolite = this->nrpolite + 1;
    c.polite = new politaasigurare*[c.nrpolite];
    for(int i = 0; i < this.nrpolite; i++)
    {
        c.polite[i] = this->polite[i];
    }
    c.polite[this->nrpolite] = p;
    return c;
}
Apropo, operatorul „+=” de obicei modifică obiectul curent (this) și returnează ‘companieasigurari &’. Implementarea anterioară seamănă mai mult a operator „+”.

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 15:05
by IVANA_27
Viorel wrote: Apropo, operatorul „+=” de obicei modifică obiectul curent (this) și returnează ‘companieasigurari &’. Implementarea anterioară seamănă mai mult a operator „+”.
Ar fi mai ok asa?

void operator += (politaasigurare *p) {
politaasigurare **aux = polite;
this->polite = new politaasigurare* [this->nrpolite+1];
for (int i=0; i<this->nrpolite; i++)
this->polite = aux;
this->polite[this->nrpolite] = p;
this->nrpolite++;
delete [] aux;
}

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 15:43
by Ovidiu Cucu
@Viorel:
Vezi ca ai intors referinta (companieasigurari&) la un obiect local non-static. Presupun ca-i un typo. ;)

@IVANA_27:
[ deleted stuff ]

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 15:59
by IVANA_27
Ideea e urmatoarea: am clasa politaasigurare si clasa comapnie asigurari.
In companieasigurari trebuie sa am un vector static sau dinamic de adrese - *politaasigurare.
Mie nu mi se spune explicit ca trebuie sa supraincarc operatorul +=, ci mi se spune sa supraincarc operatorii necesari pt ca in programul principal sa pot face operatiile mentionate mai sus, si anume:

companieasigurari* c=new companieasigurari();
c+=&p;

Practic companieasigurari ar trebui sa poata gestiona o lista de polite.

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 18:48
by Ovidiu Cucu
IVANA_27 wrote:[...]
mi se spune sa supraincarc operatorii necesari pt ca in programul principal sa pot face operatiile mentionate mai sus, si anume:

companieasigurari* c=new companieasigurari();
c+=&p;
Am sters postul anterior pentru ca facusem o confuzie din cauza notatiei (p din expresia c+=&p fiind obiect de tip politaasigurare si nu pointer). Oboseala... :)
Chiar si asa insa, nu-i OK.

Cum ai da-o cum ai drege-o, in declaratia de mai sus c este un pointer.
Din aritmetica pointerilor stim (sau ar trebui sa stim) ca la un pointer nu se poate aduna decat ceva de tip intreg.
Asadar, in dreapta expresiei c = &p nu putem avea decat un tip intreg. By default, &p este tot un pointer, deci nu are ce cauta acolo.

Chiar incercand giumbuslucuri, cum ar fi supraincarcarea operatorului & (address-of) in clasa politaasigurare ca sa intoarca sa zicem int (ceea ce, zic eu, e stupid & tricky), tot nu ies pasientele la sintaxa data in enunt. Cel putin nu asa usor.
In concluzie sau enuntul este gresit, sau rezolvarea e atat de tricky incat practic mai mult incurca decat ajuta.
IVANA_27 wrote: Practic companieasigurari ar trebui sa poata gestiona o lista de polite.
Practic pierdem timpul daca continuam in directia data de codul din enunt.
Scriem asa

Code: Select all

int main()
{
    companieasigurari* pCompanie = new companieasigurari;
    politaasigurare polita;

    *pCompanie += &polita;
    // ...
    delete pCompanie;

    return 0;
}
sau asa

Code: Select all

int main()
{
    companieasigurari companie;
    politaasigurare polita;

    companie += &polita;
    // ...

    return 0;
}
frumos ci clar pentru toata lumea, fara nimic tricky si fara sa fie deocamdata nevoie de supraincarcat altceva decat companieasigurari::operator+=.

Re: Legaturi_intre_clase

Posted: 26 Jan 2014, 19:11
by IVANA_27
Multumesc pt ajutor si apreciez timpul pierdut !
Pana la urma "companieasigurari" am facut-o template, ca sa pot avea si liste ce contin alte tipuri de polite, si intr-adevar, imi merge fara probleme supraincarcarea +=, daca in main scriu intr-unul din cele 2 feluri pe care mi le-ai spus:

Code: Select all

int main()
{
    companieasigurari* pCompanie = new companieasigurari;
    politaasigurare polita;

    *pCompanie += &polita;
    // ...
    delete pCompanie;

    return 0;
}
sau asa

Code: Select all

int main()
{
    companieasigurari companie;
    politaasigurare polita;

    companie += &polita;
    // ...

    return 0;
}
Multumesc inca o data! :-D

Re: Legaturi_intre_clase

Posted: 27 Jan 2014, 12:34
by Silviu Ardelean
IVANA_27 wrote:Pana la urma "companieasigurari" am facut-o template, ca sa pot avea si liste ce contin alte tipuri de polite
Imi scapa rationamentul cu template-uri pentru CompanieAsigurari.
In lumea reala ai ideea de o companie cu enspe tipuri de polite unde, fiecare, are propria particularitate. In situatia asta, nu crezi ca polimorfismul ti-ar fi fost mai de folos? Iar atunci la nivelul operatorului tau += ai fi avut ca parametru tot un pointer la PolitaAsigurare dar o metoda virtuala de genul BuildInsurance() ar fi actionat in mod diferit in functie de tipul politei (clasa derivata din PolitaAsigurare).

Asta, daca nu cumva te-ai gandit sa aplici un pattern de genul CRTP pe PolitaAsigurare si sa ai polimorfism fara virtual table. Dar cred ca mergem cam departe... :)

Re: Legaturi_intre_clase

Posted: 27 Jan 2014, 23:00
by bu7ch3r
[off-topic]
Nu ma pot abtine... += unde param e "polite" instantiaza o noua companie de asigurari, aloca pointer la polite + 1, apoi face copiere, apoi returneaza noul obiect CompanieAsigurari.... N-ar fi mai ok sa realoce politele cu polite+1 si sa adauge noua polita - sa modifice this-ul sau sa arunce exceptie daca nu poate realoca(Ar fi bine sa se poata realoca mereu :))?
Problema ar putea fi atunci cand apelezi += pe 100.000 de polite unde fiecare polita are 1 MB - ar putea fi...

Sper ca IVANA a facut o lista de clasaDeBazaPolite unde adauga descendenti a claseiDeBazaPolite sau chiar clasaDeBazaPolite, unde cum baga... e treaba ei.

[/off-topic]