c – function …已经定义了一个body&function模板
作者:互联网
我有这个头文件:
Utility.h:
#pragma once
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>
using namespace std;
template<std::size_t> struct int_ {};
template <class Tuple, size_t Pos>
std::ostream& print_tuple(std::ostream& out, const Tuple& t, int_<Pos>);
struct Timer {
public:
Timer();
void start();
double getMilliSec();
private:
LARGE_INTEGER frequency; // ticks per second
LARGE_INTEGER t1, t2; // ticks
};
//...
#include "Utility.cpp"
而这个实现文件:
Utility.cpp:
#include "Utility.h"
template <class Tuple, size_t Pos>
std::ostream& print_tuple(std::ostream& out, const Tuple& t, int_<Pos>) {
...
}
Timer::Timer() {
// get ticks per second
QueryPerformanceFrequency(&frequency);
}
void Timer::start() {
QueryPerformanceCounter(&t1);
}
double Timer::getMilliSec() {
QueryPerformanceCounter(&t2);
return (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
}
哪个返回此错误:
error C2995: 'std::ostream &print_tuple(std::ostream &,const Tuple &,int_<Pos>)': function template has already been defined
error C2084: function 'Timer::Timer(void)' already has a body
...
问题不在于警卫(如this问题所示),因为我使用#pragma一次
我已经阅读了关于模板类实现的implementing .tpp files,但我发现它是一个可怕的解决方案,因为Visual Studio将不会格式化此文件.
试图定义Utility.tpp :(错误的解决方案)
所以我用Utility.h中的#include“Utility.cpp with #include”Utility.tpp替换了…
Utility.tpp
Timer::Timer() {
// get ticks per second
QueryPerformanceFrequency(&frequency);
}
void Timer::start() {
QueryPerformanceCounter(&t1);
}
double Timer::getMilliSec() {
QueryPerformanceCounter(&t2);
return (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
}
现在返回的错误是:
1>Memoization.obj : error LNK2005: "public: __cdecl Timer::Timer(void)" (??0Timer@@QEAA@XZ) already defined in HelloWorld.obj
...
这是主要的顺便说一下:
HelloWorld.cpp:
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//#include "Memoization.cpp"
#include<vector>
#include"Utility.h"
using namespace std;
int main()
{
}
试图定义Utility.tpp :(正确的解决方案,最后)
正如在注释中注意到的那样,作为一个白痴,我在.tpp文件中导入了Time方法,显然我应该导入模板函数,因此在Utility.tpp中包含print_tuple,而Utility.cpp包含3个Timer函数.
解决方法:
如果要将cpp文件包含到头文件中,则需要在项目中排除该cpp文件.如果不这样,那么头文件将具有cpp文件所具有的内容,并且当编译器将cpp文件编译为对象时,您将拥有两个定义副本.一个在头文件中,因为它有一个cpp文件的副本,一个在cpp文件中,因为它实际上是编译的.这导致重新定义错误.
一旦从编译中删除Utility.cpp,那么包含Utility.h的任何其他cpp文件将具有完整源代码,因为还包括Utility.cpp.
要从编译中删除Utility.cpp,请参阅:How to exclude files from Visual Studio compile?
如果你使用cpp文件的唯一原因是因为tpp文件没有将C代码格式化为C,那么你可以配置MSVS将tpp文件视为C文件.如果你去工具 – >选项 – >文字编辑器 – >文件扩展名您可以为格式添加文件扩展名.在扩展框中输入扩展名,从编辑器下拉列表中选择Microsoft Visual C,然后单击“添加”.
现在您可以使用tpp文件而不是cpp文件,而不必记住从构建中排除cpp文件.您还可以遵循现代实践.
标签:c,templates,header-files 来源: https://codeday.me/bug/20191003/1850425.html