2009-10-25 14 views
10

Pimpl to źródło tablicy w wielu kodach C++. Wygląda na to, że kombinacja makr, szablonów i może trochę pomocy z zewnątrz może rozwiązać problem, ale nie jestem pewien, jaki byłby najłatwiejszy sposób. I've seen templates, które pomagają trochę podnieść, ale nie za wiele - wciąż musisz napisać funkcje przekazywania dla każdej metody klasy, którą próbujesz zawijać. Czy istnieje prostszy sposób?Zautomatyzuj pimpl'ing klas C++ - czy istnieje prosty sposób?

Wyobrażam sobie narzędzie używane jako część procesu tworzenia. Chcesz, aby twoje nagłówki publiczne były klasami pimpl'd, więc musisz podać plik wejściowy, na przykład pimpl.in, który zawiera listę klas (zaimplementowanych un-pimpl'd), które chcesz zawijać, następnie plik jest badany, klasy pimpl są generowane i tylko ich nagłówki (nie oryginalne nagłówki klasy) są instalowane podczas "make install". Problem polega na tym, że nie widzę sposobu, aby to zrobić bez pełnego parsera C++, coś, czego nawet dostawcy kompilatorów nie mogą uzyskać. Być może klasy mogłyby być napisane w jakiś sposób, co czyni pracę narzędzia zewnętrznego łatwiejszym, ale jestem pewny, że w efekcie skończyłoby się brakować różnego rodzaju przypadków narożnych (na przykład szablonowych klas i/lub szablonowych funkcji składowych).

Wszelkie pomysły? Czy ktoś jeszcze ma rozwiązanie tego problemu?

+0

Lazy C++ robi coś podobnego – Amnon

Odpowiedz

6

Nie, nie ma łatwej odpowiedzi. :-(Myślę, że prawie każdy ekspert OO mówi "preferuje kompozycję ponad dziedziczenie", będzie wsparcie językowe dla tworzenia kompozycji o wiele łatwiejsze niż dziedziczenie

0

Jedną z opcji jest użycie klasy interfejsu Zamiast:

class ClassA { 
    virtual void foo() = 0; 
    static ClassA *create(); 
}; 

// in ClassA.cpp 

class ImplA : public ClassA { 
/* ... */ 
}; 
ClassA *ClassA::create() { 
    return new ImplA(); 
} 

ta ma jednak dodać narzut od pobierania vtable wskaźników funkcji.

Poza tym nie mogę wymyślić takiego narzędzia. Jak już powiedziałeś, parsowanie C++ jest nietrywialne i istnieją inne języki tam, gdzie jest to mniejszy problem (np. C# lub Java późno wiążą wszystko, abyś mógł później bez problemów zmienić ich układ w pamięci).

+4

C# najbardziej zdecydowanie nie „późne wiążą wszystko” –

2

Nie mówię, że to jest dobre (po prostu coś, co powstało do głowy)
ale można eksperymentować z przeciążenia operatora -..>

#include <memory> 
#include <iostream> 

class X 
{ 
    public: 
    void plop() 
    { 
     std::cout << "Plop\n"; 
    } 
}; 

class PimplX 
{ 
    public: 
     PimplX() 
     { 
      pimpl.reset(new X); 
     } 
     X* operator->() 
     { 
      return pimpl.get(); 
     } 
    private: 
     PimplX(PimplX const&); 
     PimplX& operator=(PimplX const&); 
     std::auto_ptr<X> pimpl; 
}; 


int main() 
{  
    PimplX  x; 

    x->plop(); 
} 
+0

to ciekawy pomysł, chociaż będzie. w dalszym ciągu wywołuje funkcje bezpośrednio na obiekcie X, co oznacza, że ​​musisz odsłonić nagłówek i definicję X, więc X nie będzie całkowicie nieprzejrzysty. Z drugiej strony, jeśli piszczysz głównie dla ABI i nie czynisz klasy nieprzejrzystą (i możesz ufać, że użytkownicy nie tylko zdecydują się użyć X bezpośrednio zamiast, gdy jej nagłówki są dostępne), myślę, że byłoby dobrze. –

+0

Ponadto funkcje zdefiniowane w definicjach klas w C++ są niejawnie wbudowane. Musisz przenieść konstruktor PimplX i operator-> definicje z klasy, aby nie wiązać rozmówcy z ABI X. –

Powiązane problemy