有一些策略可以限制(公共)包含的数量。第一种是通过前向声明。以下是有效的 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 头文件……这将产生一个巨大的、不可读的文件。它将完整地包含在任何编译单元中,从而将您的编译时间减慢到几乎无限。
老实说,防止公共标头过载的唯一好方法是从一开始就防止它们发疯。