es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo implementar partes de las funciones miembro de una Clase en una biblioteca estática, mientras que el resto de las funciones se implementan en un archivo cpp.

Tengo una clase C++ llamada Class A de la siguiente manera:
“`
// en el archivo de encabezado A.h
class A
{
public:
void foo1();
void foo2();
private:
double m_a;
};

// en el archivo cpp A1.cpp
void A::foo1(){
m<em>a = 0; //hacer algo con m</em>a
}

// en el archivo cpp A2.cpp
void A::foo2(){
foo1(); // llamar a foo1
}

// en el archivo cpp main.cpp
int main(){
A obj;
obj.foo2();
return 0;
}
<code>
En mi caso, la función</code>foo1<code>y</code>foo2<code>son implementadas por dos personas diferentes. Por algunas razones, necesito ocultar la implementación de</code>foo1<code>para que las personas que codifican A2.cpp no puedan acceder al código fuente de</code>foo1<code>, pero al mismo tiempo puedan usar</code>Class A<code>en su propia aplicación (como en</code>main.cpp“` anterior).

Intenté archivar A1.cpp como una biblioteca estática, pero por supuesto, ocurrió un error de ‘símbolo externo no resuelto’ para foo2.

Construí mi biblioteca estática utilizando los complementos de CMake en Visual Studio 2019, y mi archivo CMakeLists.txt es así:

add_library (my_lib STATIC A1.cpp)
target_include_directories(my_lib PUBLIC path/to/A.h)

¿Existe alguna solución o una solución alternativa para este problema?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, hay una solución para este problema. Puedes utilizar el idiom Pimpl, que te permite ocultar los detalles de implementación de una clase a sus usuarios.

    Así es como puedes hacerlo para la Clase A:

    Primero, crea un nuevo archivo de encabezado A_private.h que contenga los detalles de implementación privados de la Clase A:

    // en archivo de encabezado A_private.h
    class AImpl {
    public:
        void foo1();
    private:
        double m_a;
    };
    

    Este archivo no debe incluirse en A.h.

    A continuación, modifica el archivo de encabezado A.h para utilizar el idiom Pimpl:

    // en archivo de encabezado A.h
    #include <memory>     // para std::unique_ptr
    
    class A {
    public:
        A();
        ~A();
        void foo2();
    private:
        class AImpl;        // declaración adelantada
        std::unique_ptr<aimpl> pImpl;
    };
    

    Observa que hemos reemplazado la declaración de foo1 con la declaración de la clase AImpl, que se definirá en A.cpp.

    Además, hemos agregado un miembro privado pImpl de tipo std::unique_ptr, que contendrá un puntero a la implementación real de la Clase A.

    Ahora, modifiquemos A.cpp para definir la clase AImpl e implementar foo2:

    // en archivo cpp A.cpp
    #include "A.h"
    #include "A_private.h"
    
    class A::AImpl {
    public:
        void foo1() {
            m_a = 0;  // hacer algo con m_a
        }
    private:
        double m_a;
    };
    
    A::A() : pImpl(std::make_unique<aimpl>()) {}
    
    A::~A() = default;
    
    void A::foo2() {
        pImpl->foo1();
    }
    

    Observa que hemos definido la clase AImpl dentro del alcance de la clase A, y hemos implementado foo1 dentro de ella.

    Además, hemos definido el constructor de A, que inicializa pImpl con una nueva instancia de AImpl, y el destructor de A, que se define como predeterminado.

    Finalmente, hemos implementado foo2, que llama al método foo1 del objeto AImpl apuntado por pImpl.

    Con esta implementación, los usuarios de la Clase A solo necesitarán incluir A.h, y no tendrán acceso a los detalles privados de la clase AImpl.

Comments are closed.