2009-10-25 6 views
10

Pimpl es una fuente de repetición en muchos códigos C++. Parecen el tipo de cosas que una combinación de macros, plantillas y quizás una pequeña herramienta externa podrían ayudar a resolver, pero no estoy seguro de cuál sería la forma más fácil. I've seen templates que ayudan a levantar algo, pero no mucho; aún así, necesitas escribir funciones de reenvío para cada método de la clase que estás tratando de envolver. hay una manera mas facil?Automatice pimpl'ing de las clases de C++, ¿hay alguna manera fácil?

Estoy imaginando una herramienta utilizada como parte del proceso de fabricación. Usted quiere que sus encabezados públicos sean clases con pimpin, por lo que proporciona un archivo de entrada, digamos pimpl.in, que enumera las clases (implementadas sin chulo) que le gustaría envolver, luego ese archivo es examinado, las clases pimpl se generan y solo sus encabezados (no los encabezados de la clase original) se instalan durante una 'make install'. El problema es que no veo ninguna manera de hacer esto sin un analizador de C++ completo, algo que incluso los proveedores de compiladores no pueden hacer bien. Tal vez las clases se podrían escribir de alguna manera que facilita el trabajo de una herramienta externa, pero estoy seguro de que terminaría perdiendo todo tipo de casos de esquina (por ejemplo, clases con plantilla y/o funciones de miembro con plantilla).

¿Alguna idea? ¿Alguien más ya tiene una solución para este problema?

+0

Lazy C++ hace algo similar – Amnon

Respuesta

6

No, no hay una respuesta fácil. :-(Creo que con casi todos los expertos de OO que dicen "prefieren la composición sobre la herencia", habría compatibilidad de idiomas para hacer la composición mucho más fácil que la herencia.

0

Una opción es utilizar una clase de interfaz en su lugar:

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

// in ClassA.cpp 

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

Esto sin embargo agregar una sobrecarga de ir a buscar los punteros de función vtable.

Aparte de eso, no puedo pensar en ninguna de esas herramientas. Como dijiste, analizar C++ no es trivial, y hay otros idiomas donde no es un problema (p. Ej., C# o Java vinculan todo lo último, por lo que puedes cambiar su diseño en memoria más adelante sin problemas).

+4

C# decididamente no "todo lo que late-bind" –

2

No digo que esto sea bueno (algo que surgió) a la mente)
Pero se puede experimentar con sobrecarga para el operador -..>

#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

Esa es una idea interesante, aunque se quiere. termine llamando funciones a un objeto X directamente, lo que significa que tendrá que exponer el encabezado y la definición de X, por lo que X no será totalmente opaco Por otro lado, si pides principalmente para ABI y no haces que la clase sea opaca (y puedes confiar en que los usuarios no solo optarán por usar X directamente cuando sus encabezados estén disponibles), creo que estaría bien. –

+0

Además, las funciones definidas dentro de las definiciones de clase en C++ están implícitamente en línea. Debería mover las definiciones constructor y operador de PimplX fuera de la clase para que no vincule a la persona que llama con el ABI de X. –

Cuestiones relacionadas