c++模板和继承
Posted
技术标签:
【中文标题】c++模板和继承【英文标题】:c++ templates and inheritance 【发布时间】:2010-04-22 11:14:48 【问题描述】:我在使用模板和继承将代码分解为可重用部分时遇到了一些问题。我想实现我的树类和 avltree 类使用相同的节点类,并且 avltree 类从树类继承一些方法并添加一些特定的方法。所以我想出了下面的代码。编译器在 tree.h 中抛出一个错误,如下所示,我真的不知道如何克服这个问题。任何帮助表示赞赏! :)
node.h:
#ifndef NODE_H
#define NODE_H
#include "tree.h"
template <class T>
class node
T data;
...
node()
...
friend class tree<T>;
;
#endif
树.h
#ifndef DREVO_H
#define DREVO_H
#include "node.h"
template <class T>
class tree
public: //signatures
tree();
...
void insert(const T&);
private:
node<T> *root; //missing type specifier - int assumed. Note: C++ does not support default-int
;
//implementations
#endif
avl.h
#ifndef AVL_H
#define AVL_H
#include "tree.h"
#include "node.h"
template <class T>
class avl: public tree<T>
public: //specific
int findMin() const;
...
protected:
void rotateLeft(node<T> *)const;
private:
node<T> *root;
;
#endif
avl.cpp(我尝试将头文件从实现中分离出来,在我开始将 avl 代码与树代码结合之前它就起作用了)
#include "drevo"
#include "avl.h"
#include "vozlisce.h"
template class avl<int>; //I know that only avl with int can be used like this, but currently this is doesn't matter :)
//implementations
...
【问题讨论】:
【参考方案1】:tree.h
和 node.h
都尝试相互包含,包含守卫会阻止其中一个看到另一个。
而不是 #include "tree.h"
尝试向前声明树,如:
template <class T>
class tree;
在node.h
编辑: 正如 sbi 在评论中所建议的那样,在 node.h
中转发声明 tree
比反过来更有意义,因为它是关于授予 tree
访问 @987654329 @ 通过friend
声明。
【讨论】:
我认为在"node.h"
中不使用#include "tree.h"
比反之更有意义。毕竟,很难想象如何实现没有节点的树,而对于friend
声明,tree
的前向声明就足够了。
递归包含实在是太有趣了……你知道有什么预处理器会警告那些野兽吗?我的意思是可以写 #ifdef HEADER_GUARD \n #error "HEADER_GUARD defined" \n #else
而不是 #ifndef
但它已经很混乱了......
@Matthieu M. 也许是一个宏... ;)
@Matthieu:这只会导致整个代码出现虚假错误。我们有标头保护的原因是我们经常确实在编译中多次包含同一个标头,而没有任何递归。如果 A 和 B 都包含 C,而 D 包含 A 和 B,则 C 被包含两次,并且在包含图中没有递归,也没有循环。当代码完全有效并且非常普遍时,您的建议会生成 #error。
是的,这就是我之前谈到警告的原因,应该写成#warning
。此外,即使它是完全合法的,它仍然是非常低效的。我们在编译时间方面的主要收获之一是通过清除不必要的包含来实现的(我不是指前向声明,只是不重新包含已经被另一个包含文件包含的文件)。它有点脆弱,但我们说的是那里有几十万个标题,所以查找速度很慢。奇怪的是,我们从来没有走预编译头路。【参考方案2】:
不要在“node.h”中#include“tree.h”。
此外,您已经在 tree
和 avl
类中声明了 root
。将tree::root
限定为protected
并删除avl::root
。
【讨论】:
【参考方案3】:您的问题是 tree.h 包含 node.h ,反之亦然。我不会认为节点必须知道树或授予它友谊是必要的(或有意义的),所以我将其删除。
【讨论】:
【参考方案4】:问题是由于 tree.h 和 node.h 之间的头文件的循环依赖。由于 node.h 包含 tree.h,所以在编译树类时,编译器不知道节点的类型是什么。由于您只是将它用于声明朋友,因此无需在 node.h 中包含头文件 tree.h
【讨论】:
以上是关于c++模板和继承的主要内容,如果未能解决你的问题,请参考以下文章