在头文件中包含模板实现cpp文件并链接混淆

时间:2013-06-30 05:31:32

标签: c++ hyperlink

我正在阅读一篇文章An Idiot's Guide to C++ Templates - Part 2并来到Separation of Declaration and Implementation部分。

现在我有三个文件,其内容如下:

sample.hpp

#ifndef SAMPLE_HPP
#define SAMPLE_HPP

template <typename T>
void displayValue(T tValue);

#include "sample.cpp"

#endif

sample.cpp的

#include <iostream>
template <typename T>
void displayValue(T tValue){
  std::cout<<tValue<<std::endl;
}

的main.cpp

#include "sample.hpp"
int main(void) {
  displayValue(20);
  displayValue(3.14);
  return 0;
}

据作者说,

  

您的项目/构建现在不得为编译过程添加Sample.CPP

但相反,当我使用时:

g++ main.cpp sample.cpp -o main

它仍然有效!

我认为在这种情况下,对象sample.o仍然包含有关模板函数displayValue NO 代码,而在main.o对象中,它包含。所以理论上没有错误。但为什么作者说must not

2 个答案:

答案 0 :(得分:1)

您没有收到任何错误是正常的。因为您的定义和实现被视为一个文件。

更好和通常的C ++风格是;

头文件(myClass.h): 您不应该包含实现文件(编译器会在您找到它时找到它)。 实现(myClass.cpp):      #include myClass.h

主程序(main.cpp) 这还需要 #include myClass.h

如果使用这种通常的样式实现,则只会因为您不应该分离模板函数/类的定义和实现而产生链接错误。

作者可能会指这个。

答案 1 :(得分:0)

模板是部分定义,因此可以限定它们在标题中“部分”实现。在你的情况下,

sample.hpp

#ifndef SAMPLE_HPP
#define SAMPLE_HPP

#include <iostream>
template <typename T>
void displayValue(T tValue){
  std::cout<<tValue<<std::endl;
}
#endif

的main.cpp

#include "sample.hpp"
int main(void) {
  displayValue(20);
  displayValue(3.14);
  return 0;
}

即使您在多个位置添加标题(并且非常易读),这在任何情况下都能完美运行

或者你仍然可以通过将sample.cpp包含在使用该模板的其他cpps中来保持你所做的并且“理论上正确”。这是一项更多的工作。

N.B:这不是问题的确切答案,而是绕过一切问题的方法,包括问题。