我正在阅读一篇文章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
?
答案 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:这不是问题的确切答案,而是绕过一切问题的方法,包括问题。