Differences

This shows you the differences between two versions of the page.

Link to this comparison view

sd-ca:laboratoare:laborator-03 [2016/02/21 19:37]
radu.stochitoiu
sd-ca:laboratoare:laborator-03 [2016/02/21 19:51] (current)
darius.neatu
Line 1: Line 1:
-====== ​Laborator ​03 - Notiuni avansate de C++ ======+====== ​Articol ​03 - Notiuni avansate de C++ ======
  
-Responsabili 
-  * [[andrei.vasiliu2211@cti.pub.ro| Andrei Vasiliu]] 
-  * [[daniel.ciocirlan1607@cti.pub.ro| Daniel Ciocîrlan]] 
  
 ===== Obiective ===== ===== Obiective =====
  
-În urma parcurgerii acestui ​laborator ​studentul va: +În urma parcurgerii acestui ​articol ​studentul va:  
 +  * înțelege conceptul de template
  
-  * afla funcționalitățile claselor/​funcțiilor prietene +===== Templates =====
-  * realiza supraîncărcarea operatorilor din C++ +
-  * înțelege conceptul de copy constructor +
-  * înțelege conceptul de rule of three+
  
 +Motivul principal pentru care folosim C++ în cadrul SD este datorită funcționalității oferite de template-uri.
  
 +Acestea permit generalizarea tipurilor de date folosite în interiorul funcțiilor și claselor.
 +
 +Sintaxa pentru acestea este:
 +<code c++>
 +template <class identifier>​ declaratie;
 +template <​typename identifier>​ declaratie;
 +</​code>​
 +//​declaratie//​ poate fi fie o funcție, fie o clasă.
 +Nu există nicio diferență între keyword-ul //class// și //​typename//​ - important este că ceea ce urmează după ele este un placeholder pentru un tip de date.
 +
 +==== Function Template ====
 +În primul rând template-urile pot fi aplicate funcțiilor.
 +
 +Un exemplu comun și simplu este următorul:
 +<code c++>
 +template<​typename T>
 +T getMax(T a, T b) {
 +    return a > b ? a : b;
 +}
 +</​code>​
 +
 +Funcția poate fi apelată astfel:
 +<code c++>
 +getMax<​int>​(2,​ 3);
 +getMax<​double>​(3.2,​ 4.6);
 +</​code>​
 +
 +==== Class Template ====
 +Concret, să presupunem că avem o clasă numită KeyStorage care are:
 +  *o cheie (de tip int)
 +  *un membru de date generic (al cărui tip de date nu îl știm la momentul scrierii clasei).
 +
 +Vrem să putem folosi codul clasei indiferent de tipul de date al membrului.
 +
 +Iată cum putem face acest lucru:
 +<code c++ KeyStorage.h>​
 +template<​typename T>
 +class KeyStorage {
 +public:
 +    int key;
 +    T member;
 +};
 +</​code>​
 +
 +În funcția main, să presupunem că vrem să folosim clasa cu membrul de tip long.
 +<code c++ main.cpp>​
 +#include "​KeyStorage.h"​
 +
 +int main() {
 +    KeyStorage<​long>​ keyElement;
 +    return 0;
 +}
 +</​code>​
 +
 +Practic, oriunde folosim tipul de date T în clasă, este înlocuit cu tipul pe care îl specificăm.
 +
 +==== Where'​s the magic happening? ====
 +Sunt destul de multe lucruri de spus despre template-uri,​ dar ne vom concentra pe lucrurile care schimbă modul în care ați implementat până acum.
 +
 +Template-urile sunt de fapt indicii pentru compilator pentru a genera cod la rândul lui!
 +Practic, voi îi spuneți compilatorului un șablon generic pe care ați vrea să-l folosiți și el trebuie să fie pregătit să îl pună la dispoziția voastră când aveți nevoie.
 +
 +Ce trebuie să rețineți din asta? Totul se întâmplă la **compile time**, nu la run time.
 +
 +Compilatorul practic analizează modul în care voi folosiți clasa respectivă și generează pentru fiecare mod în care o folosiți șablonul corespunzător.
 +Folosirea KeyStorage<​int>​ și KeyStorage<​float>​ determină compilatorul să genereze cod pentru ambele clase (înlocuind o dată T cu int și altă cu float).
 + 
 +==== Guideline-uri implementare ====
 +Pentru că totul se întâmplă la compile time, înseamnă că în momentul în care compilatorul întâlnește secvența de cod ce folosește template-uri trebuie să știe //toate// modurile în care aceasta este folosita.
 +
 +Asta înseamnă că:
 +  *Trebuie să scrieți întreaga implementare în header! //sau//
 +  *Scrieți descrierea clasei generice în header, în fișierul de implementare fiecare metodă declarată este de fapt o funcție cu template și la sfârșitul implementării adăugat //template class numeclasa<​numetip>//;​
 +
 +Ultimul rând de fapt forțează folosirea template-ului cu un anumit tip de date și deci compilatorul generează cod corespunzător (trebuie să scrieți asta pentru toate tipurile).
 +
 +==== Clasa KeyStorage ====
 +Iată mai jos o structură mai dezvoltată pentru clasa KeyStorage, în care cheia este setată în constructor.
 +.
 +<code c++ KeyStorage.h>​
 +template<​typename T>
 +class KeyStorage {
 +public:
 +    KeyStorage(int k);
 +    ~KeyStorage();​
 +    ​
 +    T getMember();​
 +    T setMember(T element);
 +    ​
 +private:
 +    T member;
 +    int key;
 +};
 +
 +</​code>​
 +
 +Implementarea completa a ei poate fi realizată:
 +  *în header (în cazul template-urilor,​ acest mod este cel mai indicat).
 +  *în fișierul de implementare .cc / .cpp (al cărui schelet parțial îl găsiți mai jos).
 +
 +<code c++ KeyStorage.cpp>​
 +#include "​KeyStorage.h"​
 +
 +template<​typename T>
 +KeyStorage<​T>::​KeyStorage(int k) {
 +//TODO
 +}
 +
 +template<​typename T>
 +KeyStorage<​T>::​~KeyStorage() {
 +}
 +
 +//TODO: restul metodelor.
 +
 +// La sfarsit, cu tipurile de date pe care le veti folosi.
 +template class KeyStorage<​int>;​
 +template class KeyStorage<​long>;​
 +
 +</​code>​
 +<​hidden>​
  
   -[**5p**] Implementati clasa **Fractie**,​ cu următoarele particularități:​   -[**5p**] Implementati clasa **Fractie**,​ cu următoarele particularități:​
Line 39: Line 155:
  
 <note warning>​Tipul parametrului pentru copy-constructor trebuie să fie identic cu cel al parametrului pentru operatorul de assignment</​note>​ <note warning>​Tipul parametrului pentru copy-constructor trebuie să fie identic cu cel al parametrului pentru operatorul de assignment</​note>​
-<​hidden>​+
 ===== Exerciții ===== ===== Exerciții =====
   - [**3p**] Implementați clasa **Complex**,​ cu următoarele particularități:​   - [**3p**] Implementați clasa **Complex**,​ cu următoarele particularități:​
Line 80: Line 196:
       - [**1p**] supraîncărcarea operatorului de atribuire între două obiecte de tip vector       - [**1p**] supraîncărcarea operatorului de atribuire între două obiecte de tip vector
       - [**0.5p**] supraîncărcarea operatorului de indexare [] ce va permite accesul la elementele individuale prin indexare **Operatorul de indexare** este un operator binar, având ca prim termen obiectul care se indexează, iar ca al doilea termen indicele. (//''​obiect[indice]''​ este interpretat ca ''​obiect.operator[](indice)''//​.       - [**0.5p**] supraîncărcarea operatorului de indexare [] ce va permite accesul la elementele individuale prin indexare **Operatorul de indexare** este un operator binar, având ca prim termen obiectul care se indexează, iar ca al doilea termen indicele. (//''​obiect[indice]''​ este interpretat ca ''​obiect.operator[](indice)''//​.
-</​hidden>​+
   - [**4p**] Implementaţi clasa template **Set** care să permită lucrul cu mulțimi de obiecte, cu următoarele particularități:​   - [**4p**] Implementaţi clasa template **Set** care să permită lucrul cu mulțimi de obiecte, cu următoarele particularități:​
     - Constructorul va primi dimensiunea maximă de elemente care pot fi ținute în mulțime și va aloca spațiul necesar.     - Constructorul va primi dimensiunea maximă de elemente care pot fi ținute în mulțime și va aloca spațiul necesar.
Line 91: Line 207:
       - [**0.5p**] supraîncărcarea operatorului << (pentru scriere).       - [**0.5p**] supraîncărcarea operatorului << (pentru scriere).
       - [**0.5p**] supraîncărcarea operatorului >> (pentru citire).       - [**0.5p**] supraîncărcarea operatorului >> (pentru citire).
 +</​hidden>​
sd-ca/laboratoare/laborator-03.1456076224.txt.gz · Last modified: 2016/02/21 19:37 by radu.stochitoiu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0