当前位置: 首页 > 知识库问答 >
问题:

如何避免#include对外部库的依赖

卢开济
2023-03-14

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

// Myfile.h

#include "SomeHeaderFile.h" // External library

Class MyClass
{

// My code

};

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

这类情况通常如何处理?

共有2个答案

荀正谊
2023-03-14

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

外部.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。

林正平
2023-03-14

这是一个经典的“编译防火墙”场景。有两个简单的解决方案可以做:

>

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

    使用PImpl习惯用法(或Cheshire Cat),在这里,您转发声明一个“实现”类,您只私下声明和定义这个类(在cpp文件中)。您可以使用这个私有类来放置所有依赖于外部库的代码,以避免在您的公共类(头文件中声明的那个)中有任何它的痕迹。

    下面是使用第一个选项的示例:

    #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()) { };
    

  •  类似资料:
    • 我想验证一下,给定包中的类只引用驻留在包本身中的类。然而,我遇到了一个冲突,告诉我a类依赖于例如java.lang.String,这对我来说是完全可以的。有没有一种方法可以忽略基本的java包?

    • 问题内容: 我已经这样写了HQL查询: Hibernate生成这样的sql查询: 但是当我写这样的东西: 它生成SQL: 因此,当我结合使用这种方法时,我会收到Oracle错误: 那么有没有办法对Hibernate说我只想接收一种类型的查询(旧样式或新样式)? 更新: 结合我的意思是这样的HQL查询: 因此,在这里我指定 Alarm 应该通过LEFT JOIN 与 User 连接,而不是指定如何将

    • 今天我开始学习ReactJS,一个小时后我就开始面对这个问题。。我想在页面上的div中插入一个有两行的组件。下面是我正在做的一个简化示例。 我有一个html: 渲染功能如下: 下面我调用渲染: 生成的HTML如下所示: 我不是一个非常高兴的问题,这个问题迫使我将所有内容都打包在一个div“DeadSimpleComponent”中。在没有显式DOM操作的情况下,最好且简单的解决方法是什么? 201

    • 问题内容: 某些数据库功能(例如和)很容易受到死锁的影响,因为数据库未指定将使用哪种锁定顺序。我发现有两次 讨论暗示此行为不是SQL标准指定的,更不用说具体的实现了。因此,我在假设我们无法控制锁定顺序的情况下进行操作(至少,这样做并不明显)。 如果我们不能依赖锁定顺序,应该如何避免数据库死锁? 如果我们不应该避免僵局(您将不得不非常努力地说服我),那么我们应该怎么做? 这个问题与数据库无关,所以请

    • 为类A编写单元测试时如何模拟外部依赖关系。当我以上述方式模拟依赖关系时,“a”的值没有按预期分配给100。

    • 我一直在读这方面的文章,原因是Bazel在二进制文件的中只添加了它的直接依赖项。因为是传递依赖项,所以二进制文件找不到它。 为了解决这个问题,我可以想到以下几个黑客: > 添加难看的链接器标志,告诉Bazel添加到而不是。但是,这被认为是一个坏主意,因为不推荐使用,并且不允许通过重写。 使用而不是 使用而不是. 谢了!