功能...已经有一个身体&功能模板已经定义 [英] function ... has already a body & function template has already been defined

查看:130
本文介绍了功能...已经有一个身体&功能模板已经定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个头文件:

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
...

问题不在于警卫(如中所建议问题),因为我曾经使用 #pragma c

The problem is not about guards (as suggested in this question) since I use #pragma once

我已经读过为模板类实现实现.tpp文件,但是我发现这是一个可怕的解决方案,因为Visual Studio不会对此文件进行任何格式化。

I`ve read about of implementing .tpp files for template class implementation, but I find it an horrible solution, since Visual Studio will format nothing from this file.

试图定义Utility.tpp :(错误解决方案)

所以我替换了 #include Utility.cpp #include Utility.tpp Utility.h 中一个d define ...

So I substituted #include "Utility.cpp with #include "Utility.tpp in Utility.h and define...

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
...

这是主要的btw:

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 方法,显然我应该导入模板函数,因此在<$ c中$ c> Utility.tpp 包含 print_tuple ,而 Utility.cpp 包含3个计时器函数。

As in the comment made me notice, as an idiot I imported the Time methods in the .tpp file, and obviously I should have imported the templates function, and so in Utility.tpp contains print_tuple while Utility.cpp contains the 3 Timer functions.

推荐答案

如果要将cpp文件包含在头文件中,则需要将该cpp文件排除在编译范围之外项目。如果不这样做,那么头文件将具有cpp文件所具有的内容,并且当编译器将cpp文件编译为一个对象时,您将具有定义的两个副本。头文件中的一个,因为它具有cpp文件的副本,而cpp文件中的一个,因为它是实际编译的。这会导致重新定义错误。

If you are going to include a cpp file into a header file then you need to exclude that cpp file from compiling in the project. If you do not then the header file will have what the cpp file has and when the compiler compiles the cpp file into an object you will have two copies of the of the definitions. One in the header file as it has a copy of the cpp file in it and one in the cpp file as that is what is actually compiled. This leads to the redefinition errors.

一旦从编译中删除了Utility.cpp,则包含Utility.h的任何其他cpp文件都将具有完整的源副本,因为Utility

Once you remove Utility.cpp from being compiled then any other cpp file that includes Utility.h will have a copy the full source since Utility.cpp is also included.

要从编译中删除Utility.cpp,请参见:如何从Visual Studio编译中排除文件?

To remove Utility.cpp from compiling see: How to exclude files from Visual Studio compile?

如果使用cpp文件的唯一原因是tpp文件未将C ++代码格式化为C ++,则可以将MSVS配置为将tpp文件视为C ++文件。如果转到工具->选项->文本编辑器->文件扩展名,则可以将文件扩展名添加到格式中。在扩展名框中输入扩展名,从编辑器下拉列表中选择Microsoft Visual C ++,然后单击添加。

If the only reason you are using a cpp file is because tpp files do not format C++ code as C++ then you can just configure MSVS to treat tpp files as C++ files. If you go to Tools -> Options -> Text Editor -> File Extensions you can add a file extension to the formatting. Enter the extension in the extension box, select Microsoft Visual C++ from the editor drop down and then click add.

现在,您可以使用tpp文件而不是cpp文件,并且不必记住从构建中排除cpp文件。您还可以遵守现代惯例。

Now you can use a tpp file instead of a cpp file and you do not have to remember to exclude the cpp file from the build. You also get to conform to modern practices.

这篇关于功能...已经有一个身体&amp;功能模板已经定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆