2009-10-25 14 views
10

I Pimpl sono una fonte di codice in un sacco di codice C++. Sembrano il tipo di cosa che una combinazione di macro, modelli e forse un piccolo aiuto esterno può risolvere, ma non sono sicuro di quale sia il modo più semplice. I've seen templates che aiutano a fare un po 'di sollevamento ma non di molto - si finisce comunque per dover scrivere le funzioni di inoltro per ogni metodo della classe che si sta tentando di avvolgere. C'è un modo più semplice?Automatizza il pimpling delle classi C++: esiste un modo semplice?

Sto immaginando uno strumento utilizzato come parte del processo di produzione. Vuoi che le tue intestazioni pubbliche siano classi pimpl'd, quindi fornisci un file di input, ad esempio pimpl.in, che elenca le classi (implementate un-pimpl'd) che desideri avvolgere, quindi quel file viene esaminato, le classi pimpl vengono generate e solo le intestazioni (non le intestazioni della classe originale) vengono installate durante un 'make install'. Il problema è che non vedo alcun modo per farlo senza un parser C++ completo, qualcosa che anche i produttori di compilatori non riescono a ottenere. Forse le classi potrebbero essere scritte in qualche modo che rende più facile il lavoro di uno strumento esterno, ma sono sicuro che finirei per perdere tutti i tipi di casi d'angolo (ad esempio classi basate su modelli e/o funzioni membro basate su modelli).

Qualche idea? Qualcun altro ha già una soluzione per questo problema?

+0

pigro C++ fa qualcosa di simile – Amnon

risposta

6

No, non c'è una risposta facile. Triste Penso che con quasi tutti gli esperti OO "preferisci la composizione all'ereditarietà" ci sarebbe un supporto linguistico per rendere la composizione molto più semplice dell'ereditarietà

0

Una possibilità è quella di utilizzare una classe di interfaccia, invece:

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

// in ClassA.cpp 

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

Ciò tuttavia aggiunge in testa da andare a prendere i puntatori a funzione vtable.

A parte questo, non riesco a pensare a nessuno di questi strumenti. Come hai detto, l'analisi del C++ non è banale, e ci sono altre lingue là fuori dove c'è meno di un problema (ad esempio, C# o Java late-bind tutto, quindi puoi cambiare il loro layout in memoria più tardi senza problemi).

+4

C# più decisamente non "tardo-bind tutto" –

2

Non sto dicendo che questo è buono (solo qualcosa che è saltato fuori in mente)
Ma si potrebbe sperimentare con sovraccaricare l'operatore -..>

#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

E 'un'idea interessante, anche se si. finiscono per chiamare ancora funzioni su un oggetto X direttamente, il che significa che dovrai esporre l'intestazione e la definizione di X, quindi X non sarà totalmente opaco. D'altra parte, se stai facendo il pimpling principalmente per ABI e non rendi la classe opaca (e puoi fidarti che gli utenti non sceglieranno semplicemente di usare X direttamente invece quando le intestazioni sono disponibili), penso che sarebbe OK. –

+0

Inoltre, le funzioni definite all'interno delle definizioni di classe in C++ sono implicitamente incorporate. Dovresti spostare la funzione di costruzione e l'operatore-> definizioni di PimplX dalla classe affinché non leghi il chiamante all'ABI di X. –

Problemi correlati