C++ 模板类中的循环依赖
我将循环依赖项简化为以下内容:C++ 模板类中的循环依赖,c++,templates,polymorphism,C++,Templates,Polymorphism,我将循环依赖项简化为以下内容: // Bar.h struct Bar {}; // Base.h #include "Foo.h" struct Bar; struct Base { void func(std::shared_ptr<Foo<Bar>> foobar); // use methods of Foo in some way. }; // Derived.h #include "Base.h" struct Derived : public B
// Bar.h
struct Bar {};
// Base.h
#include "Foo.h"
struct Bar;
struct Base {
void func(std::shared_ptr<Foo<Bar>> foobar); // use methods of Foo in some way.
};
// Derived.h
#include "Base.h"
struct Derived : public Base {};
// Foo.h
#include "Derived.h"
template <typename T>
struct Foo {
void func(std::shared_ptr<Derived> d) {
// use methods of Derived in some way.
}
};
//Bar.h
结构条{};
//Base.h
#包括“Foo.h”
结构杆;
结构基{
void func(std::shared_ptr foobar);//以某种方式使用Foo的方法。
};
//导出的.h
#包括“Base.h”
派生结构:公共基{};
//福安
#包括“派生的.h”
模板
结构Foo{
无效函数(标准::共享\u ptr d){
//使用以某种方式导出的方法。
}
};
我不能在Base.h
中简单地转发declareFoo
,因为它是一个模板类,不能在Derived.h
中转发declareBase
,因为多态性,也不能在Foo.h
中转发declareDerived
,因为Foo::func
使用Derived
的成员
我以前读过关于将模板实现从声明中分离出来的内容,但我不知道最佳实践,也不确定它在这种情况下是否有效。这两个,派生的
和Foo
在我的程序中被广泛使用
如何解决此依赖关系?声明采用
std::shared\u ptr
的函数不需要类型的完整定义,只需(向前)声明即可。这允许您避免使用派生.h(在Foo.h中)和/或Foo.h(在Base.h中)的#include
,在相互引用的类中启用内联函数:
标题A.h
struct B;
struct A {
void a() {}
void f();
std::shared_ptr<B> b;
};
#include "A.tcc"
标题B.h
struct A;
struct B {
void b() {}
void f();
std::shared_ptr<A> a;
};
#include "B.tcc"
请确保所有文件都有标题保护 为什么不能向前声明类模板?据我所知,我不能?我有一个沉重的假设,即模板必须存在于它所使用的每个翻译单元中,因此无法向前声明。这是一个无效的假设吗?“模板必须存在于它在“是”中使用的每个翻译单元中(如果您将“使用”替换为“实例化”)。因此,不能向前宣布“错误”<代码>模板结构Foo代码>是一个格式良好的前瞻性声明。好吧,我们每天都会学到一些新东西。谢谢值得补充的是,即使类型是模板,您所说的也是正确的。这是我以前不理解的部分。@vmrob啊,这不是从你的问题中得到的。你可以在两个地方打破循环,只有一个地方需要前向声明模板类。为了使我的示例尽可能简洁,我犯了一个错误,只包含了Foo::func
的原型。在这种情况下,整个定义都应该存在,这将阻止向前声明派生的
。@vmrob否,可以稍后给出定义。只有声明才是避免循环的关键。
struct A;
struct B {
void b() {}
void f();
std::shared_ptr<A> a;
};
#include "B.tcc"
#include A.h
inline void B::f() { a->a(); }