Nytro Posted June 19, 2011 Report Posted June 19, 2011 [C++] Notiuni de limbajE un articol scris de mine inainte de examenul de POO (Programare Orientata pe Obiecte) - C++. M-am gandit ca poate ajuta cat de cat colegii mei.- Introducere- Mediu de lucru- Exerci?iul 0: caractere speciale- Exerci?iul 1: const- Exemplul 2: Constructori:- Exerci?iul 3: Func?ii virtualeAcopera notiuni de POO. E scris pentru a exemplifica probleme care pot sa apara in programe C++ si care pot fi de la usor la foarte greu de identificat. Insa este doar o mica colectie, cu explicatiile de riguare. Probleme pot fi multe si foarte variate, si am acoperit foarte putin.PS: Necesita cunostinte de POO: sa stii ce e ala constructor, constructor de copiere, derivare, cateva notiuni cel putin elementare."Citat":S? lu?m acum un exemplu mai interesant. Lu?m clasele Test ?i Test2, care e derivat? din Test, ambele cu parametru int implicit 0. ?i cre?m un obiect x ?i înc? unul y = x.#include <iostream>using namespace std;class Test{ int x; public: Test(int i = 0) : x(i) { cout << "Test: " << i << "\n" ; } ~Test() { cout << "~Test: " << x << "\n" ; }};class Test2: public Test{ int y; public: Test2(int i = 0) : y(i) { cout << "Test2: " << i << "\n" ; } ~Test2() { cout << "~Test2: " << y << "\n" ; }};int main(){ Test2 x(3), y = x; return 0;}În ce ordine se vor apela constructorii? E simplu:Test: 0 - Pentru x, mai întâi se apeleaz? constructorul clasei de baz? cu valoarea implicit?Test2: 3 - Apoi constructorul s?u, Test2, cu valoarea 3~Test2: 3 - Destructor y~Test: 0 - Destructorul clasei de baz?~Test2: 3 - Destructor x~Test: 0 - Destructorul clasei de baz?Ce se întâmpl? apoi? E simplu: pentru y nu se apeleaz? constructorul normal, ci se apeleaz? constructorul de copiere, care nu este definit de noi. Deci se creaz? y, un al doilea obiect, de aceea vedem c? se apeleaz? de dou? ori seria ~Test2/~Test.Îns? lucrurile devin mai interesante dac? definim un constructor de copiere pentru Test2. S? îl definim ?i s? increment?m cu 1 valoarea lui y (din Test2) pentru a face diferen?a între obiectele x ?i y.Test2(Test2 &ob) { cout << "Copiere Test2\n" ; y = ob.y + 1; }La rulare, se va afi?a:Test: 0 - Pentru x - bazaTest2: 3 - Pentru x – constructorul din derivat?Test: 0 - Interesant. Acum, înaintea constructorului de copiere care se apeleaz? la crearea lui y, se apeleaz? constructorul din clasa de baz? pentru y. Motivul e simplu: se creaz? un nou obiect Test2 ?i asta presupune apelul constructorului clasei de baz?, clasa Test. În primul caz, în care nu aveam un constructor de copiere, x-ul se copia bit cu bit in y ?i nu se mai apela niciun constructor al clasei de baz?. A?adar, aten?ie la astfel de lucruri m?runteCopiere Test2 - Se apeleaz? ?i constructorul de copiere~Test2: 4 - Destructorul lui y mai întâi, destructorii se apeleaz? în ordine invers?~Test: 0 - Destructorul din baz? al lui y~Test2: 3 - Destructorul lui x~Test: 0 - Destructorul din baz? al lui xDownload:http://www.speedyshare.com/files/29050808/C_notiuni_de_limbaj.pdfhttp://www.mediafire.com/?sn66k96645034tjhttp://www.megaupload.com/?d=RZ13C013RTTI - Runtime Type Identification/Information:E o facilitate a limbajului care permite identificarea tipului variabilelor la executie. Pentru inceput e necesar un header:#include <typeinfo>Utilitatea lui e urmatoarea: poti identifica tipul unei variabile, de obicei pointer, la executie, si poti preveni anumite erori.Sa zicem ca avem o clasa A, o clasa B care o mosteneste pe A, si o clasa C care o mosteneste pe A.Folosind un pointer la A vom putea indica catre un obiect de tipul A, B sau C, si e posibil sa nu stim sigur catre ce tip de obiect indica pointerul.A *p;Putem avea:p = new A; // Clasicp = new B; // B fiind derivata din Ap = new C; // Putem crea p-ul in functie de niste date introduse de la tastatura de exemplu, deci nu putem stii catre ce tip indica, aici ne ajuta RTTI-ul.Pentru a obtine tipul unei variabile, apelam functia "typeid()". Functia NU returneaza un sir de caractere care reprezinta numele tipului variabilelei, ci returneaza un obiect de tipul "type_info". Aceasta este de fapt o clasa cu cateva metode. Deci functia va returna un obiect care are metodele:- name() - Cea mai importanta metoda, returneaza un sir de caractere care reprezinta numele tipului variabilei (pointer, obiect, int... ) ca parametru. De exemplu, typeid(x).name va fi "i" in cazul in care x e un int, va fi "l" pentru cazul in care e un long si asa mai departe. Insa utilitatea apare la pointeri cand lucram cu clase derivate. Sa luam urmatoarele clase:class C1{ public: C1() { cout << "C1\n"; }};class C2: public C1{ public: C2() { cout << "C2\n"; }};Apoi vrem sa cream un pointer si sa vedem tipul sau:int main(){ C1 *x = new C1; cout << typeid(x).name(); return 0;}E cazul clasic, se va afisa "P2C1". "P" = pointer, "2"-ul reprezinta numarul de caractere al numelui clasei. Clasa "C1" are 2 caractere, daca aveam clasa "Test" aveam 4 caractere. Iar "C1" reprezinta desigur tipul pointerului.De asemenea:C1 *x = new C2;cout << typeid(x).name();Va afisa TOT "P2C1" pentru c x este un pointer la tipul C1, chiar daca indica spre un obiect de tipul C2.De asemenea:C1 *x = new C2;cout << typeid(*x).name();Va afisa "2C2", deci va afisa ca indica spre un obiect de tipul C2. Despre type_info ar mai fi important ca supraincarca operatorul ==, astfel poti compara typeid(x) == typeid(y). La fel si !=.E scris pe la 23:00 - 24:00 inainte de examen, nu am avut timp sa scriu mai mult.Sper sa va ajute. Quote