【发布时间】:2014-03-04 14:35:28
【问题描述】:
我一直在寻找一种分离模板类声明和定义的方法。我被推荐了一个解决方案,它在 Header.h 和 Source.cpp 中都包含防护,并且 Header.h 在包含防护的#endif 之后包含 Source.cpp。
我认为链接器会抱怨模板类的重新定义(多个符号?),但不知何故没有,为什么不呢?
这不会导致二进制结果中的重复代码吗?每次在源文件中包含头文件时,也会包含同一个类的定义。
【问题讨论】:
我一直在寻找一种分离模板类声明和定义的方法。我被推荐了一个解决方案,它在 Header.h 和 Source.cpp 中都包含防护,并且 Header.h 在包含防护的#endif 之后包含 Source.cpp。
我认为链接器会抱怨模板类的重新定义(多个符号?),但不知何故没有,为什么不呢?
这不会导致二进制结果中的重复代码吗?每次在源文件中包含头文件时,也会包含同一个类的定义。
【问题讨论】:
对于普通符号,这确实会导致双重定义。但是,模板被区别对待,就好像它们具有内部链接一样。因此,没有双重定义。
但是,将实现放入 cpp 文件中显然是个坏主意——这会混淆许多工具链,它们按照惯例假定要编译此类文件。将文件重命名为 ipp - 这通常用于此类模板实现文件。
【讨论】:
通过编译每个 CPP 文件创建的目标文件将包含重复项。链接器会删除这些重复项。
【讨论】:
【讨论】:
符号不是多重定义的,因为模板函数是内联的。
在 .cpp 文件中包含 .h 然后在 .h 文件中包含 .cpp 文件可以正常工作,因为 .h 文件有保护,因此头文件不包含 2 次。
总体而言,为此使用 .cpp 文件不是一个好主意,因为它非常令人困惑,简而言之,这与仅在 .h 文件中包含实现相同。您可以使用 _Impl.hpp 索引创建单独的 .hpp 文件来存储实现。
【讨论】:
您还必须在实现文件中包含标头保护。无论如何都不要使用 .cpp,这很令人困惑。例如,我将声明放在 header.h 中,将实现放在 header-inl.h 中。
【讨论】: