首先,我想说,我知道以前曾有人问过此类问题(例如此处 Resolving a Circular Dependency between Template Classes )。
但是,这种解决方案(将声明与实现分离)仅在将两个类放入一个文件时才有效。就我而言,我有一个 StateManager 和一个 State 类,它们都相当大并且保证会增长。因此,将它们放在一个大文件中似乎对我来说并不令人满意。
这里有一些重要的代码片段:
// Forward declare the StateManager --> does not work (incomplete type)
class State
{
public:
template <class TData>
void RequestStackPush(ID stateId, std::shared_ptr<TData> data);
private:
StateManager & stataManager;
}
这里是RequestStackPush()
方法的实现
template<class TData>
inline void State::RequestStackPush(ID stateId, std::shared_ptr<TData> data)
{
// Uses the state manager's PushState() method - here the issue with the incomplete type arises
stateManager.PushState<TData>(stateId, data);
}
显然,StateManager
始终使用 State
类。它创建它调用方法等,因此前向声明在这里不是解决方案。只是给你举个例子:
template<class TData>
inline void StateManager::PushState(State::ID stateId, std::shared_ptr<TData> data)
{
std::unique_ptr<BasePendingChange> pendingChange = std::make_unique<PendingPushDataChange<TData>>(Push, stateId, data);
pendingChangeQueue.push(std::move(pendingChange));
}
目前,这两个类都在一个大文件中。首先,声明 State
类,并向前声明 StateManager
,然后声明 StateManager
类,然后执行上述内容描述了 State::RequestStackPush()
方法,最后实现了所有 StateManager 模板方法。
如何将其分成两个不同的文件?
最佳答案
However, this solution (Separating the declaration from the implementation) only works when putting both classes into one file.
不,它不仅仅适用于一个文件。您始终可以通过包含子 header 来构建相同的文件。它只要求您做一些对于非模板来说不常见的事情(尽管相同的技术适用于所有内联函数定义):您需要在定义类后包含一个文件。尽管给定了标题,但标题并不限于位于文件顶部。
所以,在一个文件中:
- 声明
StateManager
- 定义
状态
- 包含
StateManager
的定义 - 定义依赖于
StateManager
定义的成员函数
其他文件中没有任何异常:
- 包含
状态
的定义 - 定义
StateManager
及其成员函数。
最终结果是,包含任一 header 都会按所需顺序生成相同的定义和声明。因此,这种文件分割对于限制因修改 header 之一而导致的重新编译量毫无帮助。
这可能是一个品味问题,但我总是在类的定义之后包含内联函数(包括模板和模板函数的成员)所需的定义。这样我就不用担心是否有必要这样做。
关于c++ - 模板循环依赖 - 不同文件中的单独类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47810018/