uni的一位教授希望我们使用std::vector
来实现堆栈,并编写一个"取消堆栈"它的迭代器(也就是迭代器,当迭代时弹出堆栈的顶部)
一切都可以没事,直到他还决定他希望所有这些都是通用的,使用模板和所有。那是什么时候开始的。
所以我做的第一件事就是写template<typename T> class VectorStack
:
//file VectorStack.hpp
template <typename T>
class VectorStack
{
public:
VectorStack();
virtual size_t size();
virtual bool empty();
virtual void push(T obj);
virtual T pop();
private:
vector<T> _data;
};
此处的实施可能不相关,因此我将跳过它。不要犹豫,问你是否需要它。
然后我不得不写template<typename T> class VectorStackIterator
...
VectorStack
的实例,必须至少包含指向该实例的指针。因此VectorStackIterator
需要了解VectorStack
,这会引导我们进行第一次前瞻声明。VectorStack
还有begin()
和end()
方法,这些方法应该返回VectorStackIterator
。因此VectorStack
还需要了解VectorStackIterator
,这会引导我们进行第二次前瞻声明。所以我在一个单独的文件中写了我的迭代器:
//file VectorStackIterator.hpp
template<typename T>
class VectorStack; //Forward declaration of the VectorStack
template<typename T>
class VectorStackIterator : public iterator<random_access_iterator_tag, VectorStack<T>>
{
public:
VectorStackIterator(size_t n, VectorStack<T>* instance);
T operator--();
bool operator==(VectorStackIterator other);
bool operator!=(VectorStackIterator other);
private:
VectorStackIterator();
T& operator=() {};
size_t _n;
VectorStack<T>* _instance;
};
...并将我的VectorStack
更新为:
//file VectorStack.hpp
template<typename T>
class VectorStackIterator; //Forward declaration of the iterator
template <typename T>
class VectorStack
{
public:
//...
VectorStackIterator<T> top();
VectorStackIterator<T> bottom();
//...
};
同样,迭代器的实现可能不相关
此时,我已经让编译器尖叫,因为我到处都在使用incomplete types
。所以我尝试了其他的东西:我将VectorStack
和VectorStackIterator
的声明放在同一个文件的开头,而只放,我把定义所有的方法。这是它的样子:
//file VectorStack.hpp
#ifndef VECTOR_STACK_HPP
#define VECTOR_STACK_HPP
#include <vector>
using std::vector;
#include <iterator>
using std::iterator;
#include <exception>
using std::out_of_range;
template <typename T>
class VectorStack;
//still had to forward-declare this because VectorStackIterator uses it in its own declaration.
//Class declaration (VectorStackIterator)
template<typename T>
class VectorStackIterator : public iterator<random_access_iterator_tag, VectorStack<T>>
{
public:
VectorStackIterator(size_t n, VectorStack<T>* instance);
T operator--();
bool operator==(VectorStackIterator other);
bool operator!=(VectorStackIterator other);
private:
VectorStackIterator();
T& operator=() {};
size_t _n;
VectorStack<T>* _instance;
};
//Class declaration (VectorStack)
template <typename T>
class VectorStack
{
public:
VectorStack();
virtual size_t size();
virtual bool empty();
virtual void push(T obj);
virtual T pop();
VectorStackIterator<T> top();
VectorStackIterator<T> bottom();
private:
vector<T> _data;
};
所有这些都是上面声明的每个方法的定义。我不会想到错误所在,但请问您是否要我提供。
这是我对解决方案的最接近的尝试,但是当我在Incomplete types not allowed here
函数中声明VectorStack<int>
对象时,编译器仍抱怨main
:
#include "VectorStack.hpp"
int main(int argc, char** argv)
{
VectorStack<int> v; //Incomplete types not allowed here
v.push(0); //Incomplete types not allowed here
v.push(1); //Incomplete types not allowed here
v.push(2); //Incomplete types not allowed here
for (auto it = v.top(); it != v.bottom();) //Incomplete types not allowed here (x2)
{
cout << it-- << endl;
}
return 0;
}
如果我尝试向前声明迭代器而不是向量堆栈,那么向量堆栈不再是不完整的,但是迭代器是,并且我在for
循环的标题行上出现错误。登记/>
看起来编译器不会超越前向声明,而是实际的定义使一切都完整。
我的选项用完了,你有什么想法吗?
答案 0 :(得分:1)
关注你的帖子有点难。但总的来说,有一些事情需要牢记:
那就是说,我认为处理这个问题的标准方法是:
class ClassB;
class ClassA {
ClassB* or ClassB&
}
class ClassB {
ClassA
}
ClassA::implementations // These two can happen in any order, since both ClassA and ClassB are complete at this point
ClassB::implementations
由于您的两个类都是模板化的,因此需要将实现放在头文件中,因此您可能需要小心构建文件的方式,以强制执行这些部分的顺序。