无法定义在另一个类中公开声明的类(以及更多问题)

时间:2015-01-06 04:00:33

标签: c++ class oop templates

我正在创建一个程序,其中一个两个类非常密切相关,因此我想在另一个类中声明其中一个,因此用户必须使用Class :: member语法来创建和派生自这个类类型。我已经将我的程序抽象为4个类并重新创建了错误。课程是:

GraphInterface, Graph, GraphIteratorInterface, and GraphIterator.

Graph从公共界面公开派生,并与迭代器同样派生。现在因为迭代器只能用于这些图形,我希望用户必须通过

创建一个
Graph<int>::GraphIterator<int> it;

我试图通过在GraphInterface类中声明GraphIteratorInterface类,然后将其定义为单独的.h文件来实现此目的。然后我在Graph类(从GraphInterface派生)中声明GraphIterator,然后像往常一样在它自己的cpp文件中定义它。

代码就在这里:http://ideone.com/3fByCl 当我尝试运行所有内容时,我收到了错误

"error: too few template-parameter-lists class GraphInterface<V>::GraphIteratorInterface {" 

其他错误。我不明白它是如何丢失模板参数的,我绝对给它一个(V)。

编辑 - 代码在这里

#include <iostream>
#include <vector>
using namespace std;

template<class V>
class GraphInterface {
    public:
    // Abstract GraphIterator class, defined elsewhere
    template<class VE> class GraphIteratorInterface;

    virtual ~GraphInterface();

    // BFS that uses the graph iterator class to perform work on the discovered
    // vertices and edges
    virtual void BFS(V src_vertex, GraphIteratorInterface<V> *) = 0;

};

template<class V>
class Graph : public GraphInterface<V> {
    public :
    template<class VE> class GraphIterator; // implements the graph-iter interface

    ~Graph();

    void BFS(V src_vertex, GraphIterator<V> *);
};

template<class V>
class GraphInterface<V>::GraphIteratorInterface {

    virtual void examine_edge(/*Edge Object*/) = 0;
    virtual void discover_vertex(const V &) = 0;
    // ...
};

template<class V>
class Graph<V>::GraphIterator : public GraphInterface<V>::GraphIteratorInterface {
    std::vector<V> vertices;
    //.. other members not in the interface
    void examine_edge(/*Edge Object*/);
    void discover_vertex(const V &)
};

int main() {
    Graph<int> g;
    return 0;
}

1 个答案:

答案 0 :(得分:1)

首先,您可能根本不需要GraphIteratorInterfaceGraphIterator作为模板。也就是说,从

开始
template<class V>
class GraphInterface {
public:
    class GraphIteratorInterface;

并从这里继续。

以下仅说明成员模板的语言方面。您无需在实际代码中使用任何此类内容。

  1. 如果定义类模板的成员模板,语法如下:

    template<class V> 
    template<class VE>
    class GraphInterface<V>::GraphIteratorInterface { ...
    
  2. 是连续两次使用template<class XYZ>

    1. 当您使用类模板的成员模板时,您必须使用以下语法:

      template<class V> 
      template <class VE>
      class Graph<V>::GraphIterator 
        : public GraphInterface<V>::template GraphIteratorInterface<VE> {
      
    2. 也就是说,在成员模板名称之前使用::template intead ::

      使用这些修补程序的代码是here。由于与模板无关的不同问题,它仍然无法编译。

      本质上你有

      interface XI
       member interface YI
       virtual f(YI)
      
      class XC : XI
       class YC : XI::YI
       virtual f(YC)
      

      您不能覆盖这样的虚拟功能。不同的参数列表意味着它是一个不同的功能。参数密切相关,但无关紧要。 YI和YC是两种不同的类型。

      您必须重新设计界面,以免发生。 XC :: f必须使用与XI :: f相同的签名。

      您可能希望将YI设为XI的模板参数,而不是其成员。那就是:

      template<class V, class Iter>
      class GraphInterface {
        public:
          virtual void BSF(V, Iter*) = 0;
      
        template <class V> 
        class IterImpl { ...
      
        template <class V>
        class GraphImpl : public GraphInterface <V, IterImpl> { ...
      

      你不能用这种方式在GraphImpl中定义IterImpl。