向前声明的朋友模板类不需要包含标题文件
让我们有一个抽象的模板类堆栈,该堆栈将从模板中的第二类参数继承实现。
// file Stack.h
template <class T, template<typename> class Implementation>
class Stack : private Implementation<T>
{
public:
Stack() {}
virtual ~Stack() {}
void push(const T& x) { Implementation<T>::push(x); }
void pop() { Implementation<T>::pop(); }
const T& top() { return Implementation<T>::top(); }
bool empty() const { return Implementation<T>::empty(); }
};
然后,我们有一个将提供实现的类,然后用于实例化模板。
// file ListStack.h
template <class Elem>
class ListStack
{
private:
size_t _size;
struct ListNode
{
Elem _elem;
ListNode * _next;
};
ListNode * _top;
~ListStack();
friend class Stack<Elem, ListStack>;
public:
ListStack();
bool empty() const;
const Elem& top() const;
void pop();
void push(const Elem & value);
size_t size() const;
};
我宣布了Destructor私有,并将Stack类成为一个朋友类,因此只能在实例化stack类时才使用。
// file main.cpp
#include "Stack.h"
#include "ListStack.h"
int main()
{
// ListStack<int> list; cannot instaniate
Stack<int, ListStack> s;
}
问题是为什么ListStack.h不需要包含stack.h文件?
Let us have an abstract template class Stack which will inherit realisation from second class parameter in template.
// file Stack.h
template <class T, template<typename> class Implementation>
class Stack : private Implementation<T>
{
public:
Stack() {}
virtual ~Stack() {}
void push(const T& x) { Implementation<T>::push(x); }
void pop() { Implementation<T>::pop(); }
const T& top() { return Implementation<T>::top(); }
bool empty() const { return Implementation<T>::empty(); }
};
Then, we have a class that will provide implementation and then be used in instantiating a template.
// file ListStack.h
template <class Elem>
class ListStack
{
private:
size_t _size;
struct ListNode
{
Elem _elem;
ListNode * _next;
};
ListNode * _top;
~ListStack();
friend class Stack<Elem, ListStack>;
public:
ListStack();
bool empty() const;
const Elem& top() const;
void pop();
void push(const Elem & value);
size_t size() const;
};
I declared destructor private and made Stack class a friend class so it can be only used when instantiating Stack class.
// file main.cpp
#include "Stack.h"
#include "ListStack.h"
int main()
{
// ListStack<int> list; cannot instaniate
Stack<int, ListStack> s;
}
The question is why ListStack.h don't need to include Stack.h file?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为了编译模板代码,需要在某个地方调用它。在您的情况下,您有两个标题文件都定义了模板应该是什么。对模板的调用是在包含堆栈和ListStack的文件中进行的。由于您在main.cpp中创建了堆栈变量,因此您可以逃脱列表和列表stack在标题文件中彼此之间不认识的列表。
我怀疑编译器将在您的Main.cpp中定义堆栈类,但我不确定我是否对此表示正确。
至于ListStack类实例化错误,这是因为您的灾难是私人的。检查此 link 有关更多详细信息。
编辑:您还需要为ListStack类创建定义。没有这些,什么都不会起作用。我以简单的态度假设您到处都有空的定义。
In order for template code to be compiled, it needs to be called somewhere. In your case, you have two header files both defining what a template should be. The call to the template is being made in a file that includes both Stack and ListStack. Since you are creating the Stack variable in main.cpp, you can get away with List and ListStack not knowing each other in the header files.
I suspect that the Stack class will be defined in your main.cpp by the compiler but I'm not sure if I'm right about it.
As for the ListStack class instantiation error, that's because your destructor is private. Check this LINK for more details.
EDIT: You also need to create definitions for your ListStack class. Without that, nothing will work. I assumed for simplicity that you have empty definitions everywhere.