2010-02-16 13 views
24

¿Puede alguien darme un ejemplo de cómo funcionan los encabezados públicos y privados? He leído algo en la red, pero parece que no puedo encontrar mucha información útil con códigos de muestra. Me aconsejaron que debería usar encabezados privados para separar las partes pública y privada de mi código para crear una biblioteca estática. Después de leerlo, tengo una idea general de cómo funciona, pero realmente apreciaría un buen ejemplo para comenzar. Específicamente, lo que no entiendo del todo es cómo poner las funciones de interfaz en mi encabezado público y las variables/funciones privadas en mi encabezado privado. ¡Gracias!Ejemplo de encabezado privado/público?

EDIT:

Tal vez no estoy redacción mi pregunta correcta, pero lo que quiero decir es, por ejemplo, tengo myMath.h y myMath.cpp, y tiene myMath.h:

class myMath{ 
public: 
    void initialise(double _a, double _b); 
    double add(); 
    double subtract(); 

private: 
    double a; 
    double b; 
}; 

Y myMath.cpp tiene las implementaciones de las funciones. ¿Cómo puedo hacerlo para que myMath.h solo tenga las tres funciones públicas, y las variables privadas se definan en otro archivo (por ejemplo, myMath_i.h), y estos tres archivos estén de tal manera que después de crear una biblioteca estática, solo myMath.h es necesario para los usuarios. Esto también significa que myMath.h no puede #incluir myMath_i.h. Así que algo como:

myMath.h:

class myMath{ 
public: 
    void initialise(double _a, double _b); 
    double add(); 
    double subtract(); 
} 

y myMath_i.h:

class myMath{ 
private: 
    double a; 
    double b; 
} 

Por supuesto, eso no es posible, porque entonces voy a estar redefiniendo el MyMath clase ...

Respuesta

18

Tiene dos MyClass.h archivos de cabecera y MyClass_p.h y un archivo de origen: MyClass.cpp.

permite echar un vistazo a lo que hay dentro de ellos:

MyClass_p.h:

// Header Guard Here 
class MyClassPrivate 
{ 
public: 
    int a; 
    bool b; 
    //more data members; 
} 

MiClase.h:

// Header Guard Here 
class MyClassPrivate; 
class MyClass 
{ 
public: 
    MyClass(); 
    ~MyClass(); 
    void method1(); 
    int method2(); 
private: 
    MyClassPrivate* mData; 
} 

MyClass.cpp:

#include "MyClass.h" 
#include "MyClass_p.h" 

MyClass::MyClass() 
{ 
    mData = new MyClassPrivate(); 
} 

MyClass::~MyClass() 
{ 
    delete mData; 
} 

void MyClass::method1() 
{ 
    //do stuff 
} 

int MyClass::method2() 
{ 
    return stuff; 
} 

mantener sus datos en MyClassPrivate y distribuir MyClass.h.

+1

Esto va más allá de limitarse a proporcionar cabeceras públicas y privadas y muestra el idioma pImpl también - pública/privada es necesaria para ello, pero pImpl no es necesario. –

+1

@AndrewAylett, ¿cómo harías esto sin chulo? –

+0

@LyndenShields, quería decir que puedes tener encabezados públicos y privados por motivos distintos a los pimpl, por lo que demostrar pimpl demuestra un uso específico para encabezados públicos/privados, no la idea genérica. –

9

se puede declarar todas las interfaces y las constantes desee exponer al usuario de la biblioteca en un archivo de cabecera por separado (o un conjunto de archivos) y ponerlo en "inc" subdirectorio - esas cabeceras serán "pública ". También usará otros archivos de encabezado para declarar clases y cosas que no quiere exponer, ya que son detalles de implementación: colocará esos archivos en el subdirectorio "src", que serán "privados".

De esta forma se le dará al usuario una pista de que debe incluir solo los encabezados públicos, los que están en "inc" y solo esos encabezados contienen lo que realmente necesita, mientras que los demás son "privados" y fuera de su área de interés, a menos que quiera leer sobre la implementación.

Cuando publica su biblioteca como binaria, ya sea biblioteca estática o dinámica, solo copia el contenido "inc" y el resultado de compilación, eso es suficiente para el usuario y de esta manera no ve sus fuentes de implementación.

2

cabeceras públicos son aquellos que necesitan los usuarios de la biblioteca. Los encabezados privados son aquellos necesarios para compilar la biblioteca, pero que no son necesarios para los usuarios de la biblioteca. Realizar la división puede ser bastante complicado, y muchas bibliotecas simplemente no se molestan.

0

Me preguntaba lo mismo ya que estoy cambiando de C a C++ como mi lenguaje de programación principal. Supongo que la mejor manera es usar interfaces (clases abstractas en C++): publica una interfaz pública, y su implementación privada solo usa la interfaz como clase base.

2

De hecho, he encontrado el enfoque de dos cabecera de una sola fuente a ser frágiles. Si olvida actualizar el encabezado 'public' después de cambiar el encabezado 'private', su código puede compilarse, y luego segfault en otro lugar en tiempo de ejecución. Me ha sucedido esto algunas veces, así que prefiero escribir código que no se compilará a menos que todo sea correcto.

MyClass.cpp se implementa como esto:

#define MYCLASS_IMPL 
#include "MyClass.h" 

// Implementation follows 
... 

MyClass.h es la parte interesante:

#ifdef MYCLASS_IMPL 
#include everything needed for the private: section 
#endif 

#include everything needed for the public: section only 

class MyClass 
{ 
public: 
    // Everything that's public 

#ifdef MYCLASS_IMPL 
private: 

    // Implementation details 

#endif 
}; 

Si el objetivo es ocultar los detalles de implementación (por ejemplo, una biblioteca cerrada), es posible que deba ir con el enfoque de dos encabezados. Si no desea arrastrar dependencias solo para usar una clase, el enfoque de un solo encabezado puede ser una solución simple y sólida.


Para hacer frente a la pregunta de Arton: Ha pasado un tiempo desde que he mirado esto, pero creo que el problema tenía que ver con crear instancias de objetos basado en la cabecera pública, a continuación, suponiendo un tamaño de objeto diferente con el sector privado encabezamiento. En el tiempo de ejecución, una compensación en el objeto no coincidiría, causando un golpe de memoria. Parece que la respuesta de Erenlender cubre este caso con un par de clases público/privado.

+0

¿Podría dar un ejemplo simple de "Si olvida actualizar el encabezado 'público' después de cambiar el encabezado 'privado', su código puede compilarse, y luego ..."? ¡Gracias! – Arton