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.hnode.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”。

此外,您已经在 treeavl 类中声明了 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++模板和继承的主要内容,如果未能解决你的问题,请参考以下文章

c++重用和模板

C++:类模板遇到继承

C++:从模板参数继承类

C++中模板参数的类继承

C++模板类的继承

C++ 提高教程 模板-类模板雨继承