在编写模板类时,我想将实现移动到另一个文件(myclass.tpp
)中,并将其包含在主标头(myclass.hpp
)的底部。
我的问题是:我需要在.tpp
文件中包含防护措施,还是在.hpp
文件中包含防护措施就足够了?
示例代码:
myclass.hpp
#ifndef MYCLASS_HPP
#define MYCLASS_HPP
template<typename T>
class MyClass
{
public:
T foo(T obj);
};
//include template implemetation
#include "myclass.tpp"
#endif
myclass.tpp
#ifndef MYCLASS_TPP //needed?
#define MYCLASS_TPP //needed?
template<typename T>
T MyClass<T>::foo(T obj)
{
return obj;
}
#endif //needed?
答案 0 :(得分:13)
我是否需要在.tpp文件中包含防护,还是在.hpp文件中包含防护就足够了?
永远不需要 包含防护:它们只是非常有用,便宜,无干扰且可以预期的。因此,是的,您应该使用标头防护来保护这两个文件:
#include
的大多数用例(我有一位不知道如何编写宏的同事,所以他{{1} } d实现文件 * facepalm * )。我借此机会重点介绍StoryTeller的评论:
如果未定义hpp防护,我会更进一步并添加一个描述性的
#include
指令。只是为了向包括tpp在内的人们提供一点保护。
这将翻译为:
#error
注意:如果翻译单元首先#ifndef MYCLASS_TPP
#define MYCLASS_TPP
#ifndef MYCLASS_HPP
#error __FILE__ should only be included from myclass.hpp.
#endif // MYCLASS_HPP
template<typename T>
T MyClass<T>::foo(T obj)
{
return obj;
}
#endif // MYCLASS_TPP
,然后#include <myclass.hpp>
,则不会引发错误,一切都很好。
答案 1 :(得分:3)
仅在所有头文件中使用pragma once
。编译器将确保您的文件仅被包含一次。编译器可能只会在非常不合理的情况下无法识别:有人使用硬链接来构造其包含目录。这是谁如果某人找不到其文件的唯一名称,为什么他会更熟练地为所有头文件的每个include防护找到唯一的名称?
另一方面,由于宏的名称不是唯一的,包括复制/粘贴或通过首先复制另一个而创建的头文件,等等,所以包括保护可能会被破坏...
如何选择唯一的宏名称:<project name>_<filename>
?与基于整个根目录结构的唯一性相比,它有什么独特性?
因此,最后,应该在包含保护或pragma once
之间进行选择时,应考虑确保唯一性所需的工作成本:
1-对于pragma once
,您只需确保不会由于硬链接而弄乱系统的结构化目录。
2-对于系统上每个文件的 include guard ,您应确保宏名称是唯一的。
我的意思是,作为一名经理,评估这项工作的成本和失败风险的确只有一种选择。包含防护仅在不执行评估时才使用:这是一个未决定的事情。