代码之家  ›  专栏  ›  技术社区  ›  Adrian Albert Koch

模板循环依赖关系-在不同文件中分离类

  •  2
  • Adrian Albert Koch  · 技术社区  · 7 年前

    首先,我想说,我知道以前有人问过这种问题(例如这里 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));
        }
    

    目前,这两个类都在一个大文件中。首先,声明 状态 使用 StateManager状态管理器 前向声明,后接 StateManager状态管理器 类,然后实现上述 State::RequestStackPush() 方法,最后是所有StateManager模板方法的实现。

    如何将此文件分为两个不同的文件?

    1 回复  |  直到 7 年前
        1
  •  2
  •   eerorika    7 年前

    然而,这种解决方案(将声明与实现分离)仅在将两个类放在一个文件中时有效。

    不,它不仅仅在一个文件中工作。您始终可以通过包含子标题来构造相同的文件。它只需要您做一些与非模板不寻常的事情(尽管相同的技术适用于所有内联函数定义):您需要在定义类之后包含一个文件。标题不限于位于文件的顶部,不管它们的名称如何。

    因此,在一个文件中:

    • 声明 StateManager
    • 定义 State
    • 包括的定义 StateManager状态管理器
    • 定义依赖定义的成员函数 StateManager状态管理器

    其他文件中没有异常:

    • 包括的定义 状态
    • 定义 StateManager状态管理器 及其成员功能。

    最终的结果是,包含任何一个标头都会按要求的顺序生成相同的定义和声明。因此,这种文件拆分对限制修改其中一个标头所导致的重新编译量没有任何帮助。

    这可能是一个品味问题,但我总是在类定义之后包含内联函数(包括模板和模板函数的成员)所需的定义。这样我就不必担心这样做是否必要了。