我可以在Matrix类的迭代器中避免循环依赖吗?

时间:2010-05-18 13:18:44

标签: c++ class templates circular-dependency

我们有两个班级:

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本身相同的访问过程)

5 个答案:

答案 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>时,您会碰壁砖。