我们有两个班级:
template<typename T, typename Size, typename Stack, typename Sparse>
class Matrix
和
template<typename T, typename Size>
class Iterator
Matrix应该能够返回开始和结束迭代器,Iterator将保持对Matrix的引用,以通过它的接口访问元素。我们不希望Iterator依赖Matrix的内部存储来防止耦合。我们如何解决这个循环依赖问题?
(内部Storage类具有与Matrix类相同的模板参数以及与Matrix本身相同的访问过程)
答案 0 :(得分:4)
首先,转发声明Matrix类。这允许Iterator类查看Matrix类的名称,并生成指针和引用。 (它不允许Iterator类访问成员数据或调用成员函数。)
template<typename T, typename Size, typename Stack, typename Sparse>
class Matrix;
然后,定义Iterator类。此时它所能做的就是保持引用和指向Matrix的指针。 (暂无法访问Matrix的成员。)
template<typename T, typename Size>
class Iterator{
// don't define any function bodies in here
//but do put all data members and prototypes in here
};
然后定义Matrix类(可以访问Iterator成员)
template<typename T, typename Size, typename Stack, typename Sparse>
class Matrix{
// don't define any function bodies in here
//but do put all data members and prototypes in here
};
然后为每个类定义方法体。此时,两个类的方法都可以访问彼此的成员。通常,此部分位于.cpp文件中,但对于模板,它属于.h文件。
template<typename T, typename Size, typename Stack, typename Sparse>
Matrix<T,Size,Stack,Sparse>::Matrix(){ /*...*/}
template<typename T, typename Size>
Iterator<T,Size>::Iterator(){ /*...*/ }
答案 1 :(得分:4)
在这里使用嵌套类也可能是合适的,它可能会减少您需要的模板参数的数量。
template<typename T, typename Size, typename Stack, typename Sparse>
class Matrix{
public:
class Iterator{
// define Iterator members here
};
// declare Matrix members here
}
答案 2 :(得分:2)
为了迭代,迭代器通常需要知道它们迭代的内部存储 - 通常无法避免这种耦合。以地图迭代器为例 - 它必须知道地图的内部树结构才能完成它的工作。
答案 3 :(得分:1)
您可以转发声明模板。它看起来像这样:
template<typename T> struct Foo;
template <typename T> struct Bar
{
Foo<T>* foo;
};
template<typename T> struct Foo
{
T value;
Bar<T*> foobar;
};
void bla()
{
Foo<int> grml;
}
答案 4 :(得分:0)
在定义Matrix
模板之前,前向声明Iterator
模板。
请注意,当您发现Iterator<T, Size>
无法引用Matrix<T, Size, Stack, Sparse>
时,您会碰壁砖。