【问题标题】:How to make a C++ code public headers internal?如何在内部制作 C++ 代码公共标头?
【发布时间】:2014-07-02 21:48:57
【问题描述】:

我想从我的 C++ 代码构建一个dll。问题是代码有超过 200 个.h 头文件几乎都是公开的;即,当我构建dll 并且我想在另一个程序中使用它时,除了#includeing 所需函数的标头之外,我还必须提供用于构建@987654326 的所有头文件@ 给编译器。

我只需要dll 中的一些函数,但由于几乎每个头文件都有#included 一些其他头文件(即所有头文件都是公共的),我必须在使用时将所有头文件提供给编译器dll 库。

使用dll 使用几个公共标头最简单的方法是什么?我试图用一些头文件中的源代码替换每个#include "xxxx.h,以使它们独立(公共),然后构建库,但没有工作(很多错误/太麻烦)。我不想重写所有的标题。 (@Angew 在this comment 中提出了一个解决方案)

例如,我能否以某种方式编写一个包含所需函数和头文件的 cpp 文件,然后使用之前构建的 dll(包含所有头文件),然后仅使用一个构建新的 dll来自它的公共标头?

【问题讨论】:

    标签: c++ dll header-files


    【解决方案1】:

    有一些策略可以限制(公共)包含的数量。第一种是通过前向声明。以下是有效的 C++:

     struct X;
     struct Y
     {
       Y(); ~Y();
       X foo();//yes this is legal, as long as it is included before you call this function
       void bar(X&); //(with or without const)
       void baz(X*);//(with or without const)
       //use smart pointers if you know whats good for you
       X* x;
       std::vector<X> y;//Warning! X needs to be defined before destructor/default constructor!
     };
    

    然后在“x.cpp”中包含“x.h”。 “y.h”不再依赖于“x.h”,因此“x.h”可以保持私有(如有必要)。漂亮,不是吗?

    但是当 X 必须是 Y 的成员时,你会怎么做?通常,这是使用 impl 范例解决的:

     //y.h (public header file)
     #ifndef Y_H
     #define Y_H
     class Y
     {
     public:
        Y();
        ~Y();
        void foo();
     protected://or private, w/e
        class Y_impl;
        Y_impl* impl_;
     };
     #endif
     //y-impl.h
     //private header file
     #ifndef Y_IMPL_H
     #define Y_IMPL_H
     #include "y.h"
     #include "x.h"
     class Y::Y_impl
     {
     public:
        void foo();
     private:
         X x;
     };
     #endif
     //y.cpp (private source file)
     //i typically put both y and y impl definitions here, but you could split em up
     #include "y.h"
     #include "y-impl.h"
     Y::Y() { impl_ = new Y();}
     Y::~Y() { delete impl_;}
     void Y::foo() {impl_->foo();}
     void Y::Y_Impl::foo() {/*do something*/}
    

    不幸的是,这不是像 C 那样无名的语言,也不是像 C# 这样的高级自检语言。然后,您可以将 dll 用作头文件(我过度简化了,这是一个巨大的痛苦,但如果您不需要实际结构,则可行)。

    将所有这些头文件编译成一个巨大的头文件:

    真是个坏主意。但我们会接受的。

    最简单的方法是制作一个包含所有标题的中间 c-plus-plus:

     //something.cpp
     #include "x.h"
     #include "y.h"
    

    然后让编译器在扩展包含后转储调试。不幸的是,这也会扩展所有 stdlib 头文件……这将产生一个巨大的、不可读的文件。它将完整地包含在任何编译单元中,从而将您的编译时间减慢到几乎无限。

    老实说,防止公共标头过载的唯一好方法是从一开始就防止它们发疯。

    【讨论】:

    • 我想我必须采用第三种解决方案。我是否需要只 #include cpp 文件中的所有标头,然后将 cpp 提供给带有 dll 的编译器,而不是标头?
    • @user215721 不,您需要制作 CPP 文件,将 C++(和所有相关标志)编译器传递给将转储日志的魔术日志调试标志。说真的,你应该重构你的代码,这不是一个可维护的解决方案。它也可能不起作用,因为它可以剥离所有定义的守卫。你需要一个星期的时间来做一些简单的解决方案来降低公开的公共代码,这将给你增加封装,对你的最终用户隐藏实现,并保持可靠性和质量?值得。
    【解决方案2】:

    创建一个文档化、定义明确的接口。

    这意味着编写一个包含新函数的新头文件。还要为这些函数编写一个新的 .c 或 .cpp 文件。在 .cpp 文件中的那些函数中包含原始标头并调用原始函数。

    这应该让您也可以通过代码更改来保持 API 和 ABI 的稳定性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-27
      • 1970-01-01
      • 2020-12-15
      • 1970-01-01
      • 2012-10-24
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多