我已经编写了一个简单的,基于模块的模板化头文件库。对于基于模块的应用程序,我的意思是说一个人只能包含string.h
或dynarray.h
,并且 header 将提取其所有依赖项。
现在,由于该系统的工作方式,我面临类型缺失的问题。
一个模块可以:
#include
所有依赖项class Foo
#include
一个实现文件不幸的是,在某些情况下,在包含任何实现之前,需要两个接口(interface)可用。我在这里解决了这个问题:
字符串
#pragma once
// A string depends on a DynArray.
#include "dynarray.h"
template<typename E>
class String {
public:
DynArray<E> arr;
/* ... */
};
// Include the implementation of all the different functions (irrelevant here)
#include "string_impl.h"
dynarray.h
#pragma once
// The dynarray header has no direct dependencies
template<typename E>
class DynArray {
public:
/* ... */
E& Get(int index);
};
// Include the implementation of all the different functions
#include "dynarray_impl.h"
dynarray_impl.h
#pragma once
// The dynarray implementation needs the OutOfRangeException class
#include "out_of_range_exception.h"
template<typename E>
E& DynArray<E>::Get(int index) {
if (index >= size) {
throw OutOfRangeException("Some error message");
}
}
out_of_range_exception.h
class OutOfRangeException {
public:
String message;
OutOfRangeException(String message) {
/* ... */
}
};
由于在其底部包括模块的实现,因此当在某处包含
string.h
时,dynarray_impl.h
以及out_of_range_exception.h
的内容位于字符串类接口(interface)之前。因此String
没有在OutOfRangeException
中定义。显然,解决方案是仅在定义字符串接口(interface)之后延迟dynarray的实现部分(
dynarr_impl.h
)。问题是我不知道如何在不创建某种通用头文件的情况下执行此操作,该文件与基于模块的方法不兼容。 最佳答案
您的问题是接口(interface)和实现都只有一个文件。
该文件的#include
表示取决于X的接口(interface)和X的实现。
有时您只想依赖X的接口(interface)。
X接口(interface):
#include
接口(interface)class X
。 X实现:
#include
接口(interface)#include
实现class X
的实现。 从某种意义上说,这是两个独立的模块,一个模块依赖另一个模块。这允许客户端仅依赖于另一种类型的接口(interface),或仅依赖于其实现,或者首先依赖于接口(interface),然后依赖于实现。
通常,您只有
#include "X.h"
,除非您对实现有循环依赖。然后,您必须在某个地方用#include "X_interface.h"
打破链条如果您确实要使用单个头文件,则可以取消
#pragma once
并使用可以包含在“两种模式”中的头文件。这会极大地降低构建时间,因为任何这种机制都将要求编译器打开文件只是为了检查其中是否有任何代码。大多数编译器可以检测到#ifdef
header 保护符和#pragma once
,并避免重新打开它知道不会包含任何有用内容的文件。但是这种技术无法处理花哨的“可以在不同模式下多次包含”头文件。关于c++ - 修复自阻止功能,包括在基于模块的库中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47032904/