模板化继承层次结构中的循环依赖关系

时间:2016-03-29 18:48:40

标签: c++ templates c++11 c++14 circular-dependency

我有一个模板化的Base类,它有多个子类,并提供了一个抽象的execute方法。子代以不同的方式实现此方法,并且可以将执行调用委托给Base类的尾向量中的对象。 为了将对象链接到尾部,Base类提供了一些方法(createChild1,createChild2)。这是代码:

base.h

#pragma once

#include <memory>
#include <vector>

template<typename T>
class Child1;

template<typename T>
class Child2;

template<typename T>
class Base {
public:
    std::vector<std::unique_ptr<Base<T>>> tail;

    virtual void execute(const T &t) = 0;

    Base<T> &createChild1() {
        auto child = std::make_unique<Child1<T>>();
        tail.push_back(std::move(child));
        return *tail.back().get();
    }

    Base<T> &createChild2() {
        auto child = std::make_unique<Child2<T>>();
        tail.push_back(std::move(child));
        return *tail.back().get();
    }
};

child1.h

#pragma once

#include "base.h"

template<typename T>
class Child1 : public Base<T> {
public:
    virtual void execute(const T &t) {
        // do something with t
    }
};

child2.h

#pragma once

#include "base.h"

template<typename T>
class Child2 : public Base<T> {
public:
    virtual void execute(const T &t) {
        // do something with t
        // then delegate to t
        for (auto &next : tail) {
            next->execute(t);
        }
    }
};

的main.cpp

#include <iostream>

#include "child1.h"

using namespace std;

int main(int argc, char **argv) {
    Child1<int> c;
    c.createChild2().createChild1();
    c.execute(10);
    return 0;
}

如果我尝试编译,我会得到一个未定义模板的隐式实例化&#39; Child2&#39;&#34;因为在Base中,模板类Child2仅向前声明,并且当时不知道其正文。在Child1和Child2前面声明Base并在Base中包含Child1和Child2的定义并没有解决问题,因为那时Child2无法访问tail。 我该如何解决这个循环依赖? Child1,Child2和Base中的代码可以更改,但我希望保留在main中链接create调用的可能性(因此必须在Base类中声明create方法)。

1 个答案:

答案 0 :(得分:0)

解决方案是使用this-&gt;为尾部访问添加前缀。因此,必须更改child2.h:

#pragma once

#include "base.h"

template<typename T>
class Child2 : public Base<T> {
public:
    virtual void execute(const T &t) {
        // do something with t
        // then delegate to t
        for (auto &next : this->tail) {
            next->execute(t);
        }
    }
};