无法定义在另一个 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;
}
首先,您可能根本不需要 GraphIteratorInterface
和 GraphIterator
作为模板。即从
开始
template<class V>
class GraphInterface {
public:
class GraphIteratorInterface;
然后从这里继续。
以下仅涉及成员模板的语言方面。你不需要在你的真实代码中使用这些。
如果你定义一个class模板的成员模板,语法是这样的:
template<class V>
template<class VE>
class GraphInterface<V>::GraphIteratorInterface { ...
是的,连续使用template<class XYZ>
两次。
当你使用一个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。
我正在制作一个程序,其中两个 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;
}
首先,您可能根本不需要 GraphIteratorInterface
和 GraphIterator
作为模板。即从
template<class V>
class GraphInterface {
public:
class GraphIteratorInterface;
然后从这里继续。
以下仅涉及成员模板的语言方面。你不需要在你的真实代码中使用这些。
如果你定义一个class模板的成员模板,语法是这样的:
template<class V> template<class VE> class GraphInterface<V>::GraphIteratorInterface { ...
是的,连续使用template<class XYZ>
两次。
当你使用一个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。