如何使C ++代码公共头文件内部?

时间:2014-05-14 17:36:50

标签: c++ dll header-files

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

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

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

例如,我可以以某种方式编写一个包含我所需函数的cpp文件及其标题,然后使用以前构建的dll(包含所有标题),然后构建一个新的{{1}只有一个公共标题?

2 个答案:

答案 0 :(得分:2)

有一些策略可以限制(plublic)包含的数量。第一种是通过前瞻性声明。以下是有效的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标头...这将成为一个巨大的,不可读的文件。它将完整地包含在任何编译单元中,从而将编译时间减慢到几乎无限。

老实说,防止公共标头重载的唯一好方法是让它们首先不要发疯。

答案 1 :(得分:1)

创建一个记录良好,定义明确的界面。

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

这可以让你通过代码更改来维护API和ABI的稳定性。