解决循环依赖

时间:2020-07-23 04:56:40

标签: c++ templates circular-dependency

我知道那里有一些循环依赖问题,但我只是无法解决。
我有两个班:ManagerManagedManager创建Managed对象,Managed基本包装了两个Manager方法,其中一些是模板化的。

// Manager.h
struct Manager {

    Managed create(); // To be defined in the .cpp
    
    template <typename T>
    Managed create() {
        Managed managed(this); // Access Managed constructor
        managed.whatever<T>(); // Access templated function
        managed.whateverElse();
        return managed;
    }   
}

struct Managed {
    explicit Managed(Manager* manager) : manager(manager) {}
    
    template <typename T>
    void whatever() {
        manager->... // use the Manager pointer for whatever purpose
    }
    
    void whateverElse(); // To be defined in the .cpp

    Manager* manager;
}

无论如何,这是一个静态库项目。
另外,可以找到here的真实代码。

有什么办法解决这个问题?

2 个答案:

答案 0 :(得分:2)

我只是重新排序您的代码并使用PIMPL,然后建立一个小示例:

#include <iostream>

struct Managed;
struct Manager;

struct Managed {
    explicit Managed(Manager* manager) : manager(manager) {}

    template <typename T>
    void whatever() { }

    void whateverElse(); // To be defined in the .cpp

    Manager* manager;
};


struct Manager {

    Managed create(); // To be defined in the .cpp

    template <typename T>
    Managed* create() {
        Managed* m = new Managed(this);// Access Managed constructor
        m->whatever<T>(); // Access templated function
        m->whateverElse();
        return m;
    }
};

它可以那样编译。但是无论如何都应该更好地考虑这种设计。

答案 1 :(得分:0)

在处理依赖关系时要做的第一件事是在所有声明之后移动所有实现,但是您要在类内部实现方法。而是在Managed类之后执行实现。
接下来是提供所有类的前向声明。即从

开始
struct Managed;
struct Manager;

我将引用Johns的答案以提供更多代码详细信息。
(当John意识到我想将我的评论变成一篇评论时,John很仁慈地删除了他的答案。谢谢。我明确地引用了,因为无论如何我似乎都隐式地这样做,编写非常相似的代码。 约翰恳切地指出,可以编译此代码。

struct Managed;

struct Manager {

    Managed create(); // To be defined in the .cpp
    
    template <typename T>
    Managed create();
};

struct Managed {
    explicit Managed(Manager* manager) : manager(manager) {}
    
    template <typename T>
    void whatever();
    
    void whateverElse(); // To be defined in the .cpp

    Manager* manager;
};

template <typename T>
Managed Manager::create() {
    Managed managed(this); // Access Managed constructor
    managed.whatever<T>(); // Access templated function
    managed.whateverElse();
    return managed;
}   

template <typename T>
void Managed::whatever() {
    manager->create();
}