嵌套类包括头

时间:2016-05-06 21:40:09

标签: c++ templates

我有一个看起来像这样的课程:

// List.hpp
template<typename T>
class List {
    ...
private:
    class Node;
};

我想将List<T>::Node的完整定义放在一个单独的文件中:

// Node.hpp
template<typename T>
class List<T>::Node {
    ...
};

我的问题是,我应该在每个文件中包含哪些内容,以及将#include放在哪里?

最简单的方法(我认为)是在Node.hpp的末尾添加List.hpp,而不在Node.hpp中包含任何内容。但是,这使得Node.hpp本身不是一个完整的文件(比如说如果我在IDE中打开它,或者由于缺少List<T>的定义会出现很多错误)。另外,我不确定是否可以将#include放在文件的底部。

假设每个文件都有自己的包含保护#define,我还可以在List.hpp的顶部包含Node.hpp(以使IDE满意),然后包含Node.hppList.hpp的底部再次,但我不知道这是不是一个好主意。

1 个答案:

答案 0 :(得分:3)

编译List<T>::Node的成员函数时,编译器始终需要可以看到模板化的类List。这样做的结果是任何需要查看Node.hpp内容的编译单元都需要List.hpp的内容(模板化成员的定义)的可见性。

最简单的选择是将Node.hpp的内容放在List.hpp的末尾,并且只在需要任一模板的编译单元中放置#include "List.h"。这完全消除了Node.hpp的需要。

如果你真的必须有两个标题(这似乎是任意的,对我来说毫无意义,因为List<T>::NodeList<T>的一个组成部分),一个选项是帮助包含警卫。

  // List.hpp

  #ifndef LIST_HPP_INCLUDED   // some unique macro
  #define LIST_HPP_INCLUDED

  // definition of templated class List

  #include "Node.hpp"   // this must be after the definition of List<T>
  #endif

并在Node.hpp中

  // Node.hpp

  #ifndef NODE_HPP_INCLUDED   // some unique macro
  #define NODE_HPP_INCLUDED

  #include "List.hpp"     // this must precede the definitions for List<T>::Node

  // definition of templated class List<T>::Node

  #endif

这允许任何编译单元的头部都是#include d,并且包含守卫会停止无限递归包含。

大多数现代IDE都能应对这种情况。如果你有一个没有,那么只需转换到一个头文件。