Download FREE Orice
Acest forum este facut special pentru un Download FREE Orice doriti!
Lista Forumurilor Pe Tematici
Download FREE Orice | Reguli | Inregistrare | Login

POZE DOWNLOAD FREE ORICE

Nu sunteti logat.
Nou pe simpatie:
Profil Ioanacatalina
Femeie
25 ani
Salaj
cauta Barbat
25 - 61 ani
Download FREE Orice / >>>Programare<<< / Basic C++ programming techniques  
Autor
Mesaj Pagini: 1
McSpeDDy
Administrator

Inregistrat: acum 17 ani
Postari: 157
Incepem o serie in care vom discuta despre diverse tehnici de baza privind programarea in limbajul C++.


In acest snippet vom vedea cum putem simula mecanismul de polimorfism in momentul compilarii (compile time), folosind sabloane (templates) si o tehnica numita CRT (curiously recurrent template).

In mod normal, polimorfism-ul apare la runtime si se bazeaza pe mecanismul functiilor virtuale.

Sa vedem un examplu trivial:

Code:
// virtual .cpp
#include <iostream>

class Base
{
   public:
   
   virtual ~Base() {};
   
   virtual void func() = 0;
};

class Derived1 : public Base
{
   public:
   
   void func()
   {
      std::cout << "Hello from Derived1" << std::endl;
   }   
};

class Derived2 : public Base
{
   public:
   
   void func()
   {
      std::cout << "Hello from Derived2" << std::endl;
   }   
};


class Proxy
{
   public:
   Proxy(Base* param) : m_param(param) {}
   void SetParam(Base* param) { m_param = param; }
   void func() { if (m_param) m_param->func(); }
   
   private:
   Base* m_param;
};
   
int main()
{
   Derived1 myDerived1;
   Derived2 myDerived2;
   Proxy myProxy1(&myDerived1);
   myProxy1.func();
   Proxy myProxy2(&myDerived2);
   myProxy2.func();
   
   return 0;
}


Avem o clasa de baza denumita Base, din care deriveaza 2 clase Derived1 si Derived2.
In clasa de baza Base, avem declarata o functie membru virtual pura, numita func
Datorita faptului ca func este virtual pura, clasele derivate din Base vor trebui sa redefineasca functia func, altfel se va obtine o eroare la compilare.

Clasa Proxy are ca membru un pointer catre un obiect de tip Base (sau, evident, derivat din Base).

Daca compilam acest cod:

Code:
g++ virtual.cpp -o virtual


obtinem urmatorul output:

Code:
./virtual
Hello from Derived1
Hello from Derived2


Utilizarea functiilor virtuale aduce un grad mare de flexibilitate in design-ul programului, dar, aduce si un overhead: o indirectare in plus a apelului functiei virtuale prin tabelul de functii virtuale (vtable).
In marea majoritate a cazurilor, acest overhead este minor si poate fi ingnorat, dar, sunt aplicatii in care dorim performanta maxima si vrem sa eliminam acest overhead.

O solutie este utilizarea sabloanelor (templates) pentru a obtine un efect similar la compile time.
Sa vedem cum modificam exemplul precedent pentru a beneficia de aceasta tehnica.

Code:
// crtp.cpp
#include <iostream>

template <typename T>
class Base
{
   public:
   
   virtual ~Base() {};
   
   void func()
   {
      (static_cast<T*>(this))->func();
   }
};

class Derived1 : public Base<Derived1>
{
   public:
   
   void func()
   {
      std::cout << "Hello from Derived1" << std::endl;
   }   
};

class Derived2 : public Base<Derived2>
{
   public:
   
   void func()
   {
      std::cout << "Hello from Derived2" << std::endl;
   }   
};

template <typename T>
class Proxy
{
   public:
   Proxy(Base<T>* param) : m_param(param) {}
   void SetParam(Base<T>* param) { m_param = param; }
   void func() { if (m_param) m_param->func(); }
   
   private:
   Base<T>* m_param;
};
   
int main()
{
   Derived1 myDerived1;
   Derived2 myDerived2;
   Proxy<Derived1> myProxy1(&myDerived1);
   myProxy1.func();
   Proxy<Derived2> myProxy2(&myDerived2);
   myProxy2.func();
   
   return 0;
}


Clasa Base este acum o clasa sablon dupa parametrul T
Sa analizam implementare functiei membru func in clasa Base


Code:
void func()
{
   (static_cast<T*>(this))->func();
}


Aici, convertim pointerul this catre un pointer la tipul T (parametrul sablonului) si apelam functia func membra a tipului T. Ideea este faptul ca parametrul T este o clasa care are definita o functie membru numita func.
Bineinteles, vom avea grija sa instantiem corect sablonul Base

Sa analizam acum felul in care sunt declarate clasele derivate Derived1 si Derived2


Code:
class Derived1 : public Base<Derived1>
{
   public:
   
   void func()
   {
      std::cout << "Hello from Derived1" << std::endl;
   }   
};


Clasa Derived1 nu e declarata ca fiind o clasa sablon, dar deriveaza din clasa sablon Base instantiata chiar dupa tipul Derived .
Aceasta constructie poate parea complet neintuitiva unui programator novice, de aceea constructia este numita:
curiously recurrent template

Observam acum ca functia membra func nu este declarata ca fiind virtuala in clasele derivate Derived1 si Derived2

Daca apelam functia func() pe un obiect de tipul Derived1 (sau Derived2) prin intermediul unui pointer sau referinte la o instanta a clasei de baza (Base<Derived1> sau Base<Derived2>, se va apela implementarea lui func() din clasa de baza:


Code:
(static_cast<T*>(this))->func();


Dar, precum am vazut, in aceasta implementare noi convertim de fapt pointerul la instanta clasei de baza ((Base<Derived1> sau Base<Derived2> catre un pointer de tipul paramtrului sablonului dupa care s-a facut instantierea (Derived1 sau Derived2)
Deci, ca efect, ajungem sa apelam implementarea lui func() din clasa derivata (Derived1 sau Derived2)

In acest caz, clasa Proxy este tot o clasa sablon care mentine ca membru un pointer catre Base<T>.
Clasa Proxy este instantiata in functia main dupa Derived1 si Derived2

Compilare:

Code:
g++ crtp.cpp -o crtp

Executie:

Code:
./crtp
Hello from Derived1
Hello from Derived2


Aceasta tehnica este folosita de catre multe framework-uri moderne scrise folosind C++, precum WTL, SmartWin, Loki ...
Este o tehnica de baza in programarea moderna in limbajul C++.


_______________________________________

Respecta Regulile si nu vei fi banat!
Nu face reclame la alte situri nici nu ai idee de ce putem fi in stare cu situ acela!

pus acum 17 ani
   
Pagini: 1  

Mergi la