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

Unable to define a class that is declared publicly in another class (and more problems)

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

GraphInterface, Graph, GraphIteratorInterface, and GraphIterator.

其中 Graph 从其接口公开派生,迭代器也是如此。现在因为迭代器只能与这些图一起使用,我希望用户必须通过

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

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

代码在 ideone 上: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;
}

首先,您可能根本不需要 GraphIteratorInterfaceGraphIterator 作为模板。即从

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

然后从这里继续。

以下仅涉及成员模板的语言方面。你不需要在你的真实代码中使用这些。

  1. 如果你定义一个class模板的成员模板,语法是这样的:

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

是的,连续使用template<class XYZ>两次。

  1. 当你使用一个class模板的成员模板时,你必须使用这个语法:

    template<class V> 
    template <class VE>
    class Graph<V>::GraphIterator 
      : public GraphInterface<V>::template GraphIteratorInterface<VE> {
    

也就是说,在成员模板名称前使用 ::template 而不是 ::

包含这些修复的代码是 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。