如何避免#include依赖于外部库

时间:2012-12-20 19:03:45

标签: c++ dependencies static-libraries header-files

如果我正在创建一个带有头文件的静态库,例如:

// Myfile.h

#include "SomeHeaderFile.h" // External library

Class MyClass
{

// My code

};

在我自己的项目中,我可以告诉编译器(在我的例子中,Visual Studio)在哪里查找SomeHeaderFile.h。但是,我不希望我的用户关注这一点 - 他们应该能够包含我的标题,而不必通知他们的编译器有关SomeHeaderFile.h的位置。

这种情况通常如何处理?

2 个答案:

答案 0 :(得分:14)

这是一款经典的#34;编译防火墙"场景。有两个简单的解决方案:

  1. 从外部库转发声明您需要的任何类或函数。然后仅在您的cpp文件中包含外部库的头文件(当您实际需要使用在标头中转发声明的类或函数时)。

  2. 使用PImpl惯用语(或Cheshire Cat)转发声明"实现"您私有声明和定义的类(在cpp文件中)。您可以使用该私有类来放置所有与外部库相关的代码,以避免在您的公共类(在头文件中声明的那个)中有任何痕迹。

  3. 以下是使用第一个选项的示例:

    #ifndef MY_LIB_MY_HEADER_H
    #define MY_LIB_MY_HEADER_H
    
    class some_external_class;  // forward-declare external dependency.
    
    class my_class {
      public:
        // ...
        void someFunction(some_external_class& aRef);  // declare members using the forward-declared incomplete type.
    };
    
    #endif
    
    // in the cpp file:
    
    #include "my_header.h"
    #include "some_external_header.h"
    
    void my_class::someFunction(some_external_class& aRef) {
      // here, you can use all that you want from some_external_class.
    };
    

    以下是选项2的示例:

    #ifndef MY_LIB_MY_HEADER_H
    #define MY_LIB_MY_HEADER_H
    
    class my_class_impl;  // forward-declare private "implementation" class.
    
    class my_class {
      private:
        std::unique_ptr<my_class_impl> pimpl; // a vanishing facade...
      public:
        // ...
    };
    
    #endif
    
    // in the cpp file:
    
    #include "my_header.h"
    #include "some_external_header.h"
    
    class my_class_impl {
      private:
        some_external_class obj;
        // ...
      public:
        // some functions ... 
    };
    
    my_class::my_class() : pimpl(new my_class_impl()) { };
    

答案 1 :(得分:4)

假设外部头文件包含以下内容:

external.h

class foo
{
public:
   foo();
};

在您的图书馆中,您使用foo:

myheader.h:

#include "external.h"

class bar
{
...
private:
   foo* _x;
};

要使代码编译,您所要做的就是转发声明foo类(之后可以删除include):

class foo;

class bar
{
...
private:
   foo* _x;
};

然后,您必须在源文件中包含external.h。