C++ 为什么我会收到这些“已定义”链接器错误?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5333374/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:56:16  来源:igfitidea点击:

Why am I getting these 'already defined' linker errors?

c++linker

提问by SomethingsGottaGive

I am a beginner at C++ but I have some experience using Java. I am getting some errors that I don't understand. I attached a pic of the error console and the code below it.

我是 C++ 的初学者,但我有一些使用 Java 的经验。我收到了一些我不明白的错误。我附上了一张错误控制台的图片和它下面的代码。

 Error  1   error LNK2005: "public: __thiscall VectorDouble::VectorDouble(void)" (??0VectorDouble@@QAE@XZ) already defined in Main.obj  C:\Users\carrea\Code\Visual Studio\COMP201\Lab8_VectorDoubleClass\VectorDouble.obj  Lab8_VectorDoubleClass

 Error  2   error LNK2005: "public: __thiscall VectorDouble::VectorDouble(int)" (??0VectorDouble@@QAE@H@Z) already defined in Main.obj  C:\Users\carrea\Code\Visual Studio\COMP201\Lab8_VectorDoubleClass\VectorDouble.obj  Lab8_VectorDoubleClass
....    

10 more errors like these and

还有 10 个这样的错误和

 Error  13  error LNK1169: one or more multiply defined symbols found   C:\Users\carrea\Code\Visual Studio\COMP201\Lab8_VectorDoubleClass\Debug\Lab8_VectorDoubleClass.exe  1   1   Lab8_VectorDoubleClass

Main.cpp

主程序



#include "VectorDouble.cpp"
using namespace std;
void printVD(const VectorDouble& v);
int main()
{
    VectorDouble p;
    p.push_back(1);
    p.push_back(4);
    p.push_back(3);
    VectorDouble v(p);
    printVD(v);
    printVD(p);
}
void printVD(const VectorDouble& v)
{
    int n = v.size();
    for(int i = 0; i<n; i++)
    {
        cout << v.getElementAt(n) << " ";
    }
    cout << endl;
}

VectorDouble.h

VectorDouble.h



#pragma once
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <iomanip>
#include <vector>
#include <sstream>
using namespace std;
class VectorDouble
{
public:
    VectorDouble(void);
    ~VectorDouble(void);
    VectorDouble(int intSize);
    // Copy constructor
    VectorDouble(const VectorDouble& vd);
    // = override
    void operator =(const VectorDouble& RIGHT_SIDE);
private:
    double *dArray;
    int count, max_count;
public:
    // returns number of occupied cells
    int size(void) const;
    // Returns total number of cells
    int capacity(void) const;
    // Adds an element to array
    void push_back(double num);
    // Resizes the array to be double the original max_count
    void resize(void);
    // Returns element at specified index
    double getElementAt(int i) const;
    // Requests that the capacity of the allocated storage space for the elements of the vector container be at least enough to hold n elements
    void reserve(int n);
private:
    // Sets every element to 0
    void clear(void);
};

VectorDouble.cpp

VectorDouble.cpp



    #pragma once
#include "VectorDouble.h"

using namespace std;

VectorDouble::VectorDouble(void)
{
    max_count = 100;
    count = 0;
    dArray = new double[max_count];
    clear();
}

VectorDouble::VectorDouble(int intSize)
{
    max_count = intSize;
    dArray = new double[max_count];
    clear();
}

VectorDouble::~VectorDouble(void)
{
    cout << "vector with " << this->count << " is destroyed";
}

// Copy constructor
VectorDouble::VectorDouble(const VectorDouble& vd) 
{
    int mcVD = vd.capacity(), i=0;
    max_count = mcVD;
    dArray = new double[max_count];
    clear();
    while(i<max_count)
    {
        dArray[i] = vd.getElementAt(i);
        i++;
    }
}
// = override
void VectorDouble::operator =(const VectorDouble& RIGHT_SIDE)
{
    int rightCount = RIGHT_SIDE.size(), i=0;
    while(rightCount>max_count)
    {
        resize();
    }
    while(i<rightCount)
    {
        dArray[i] = RIGHT_SIDE.getElementAt(i);
        i++;
    }
    count = i;
}
// returns number of occupied cells
int VectorDouble::size(void) const
{
    return count;
}
// Returns total number of cells
int VectorDouble::capacity(void) const
{
    return max_count;
}
// Adds an element to array
void VectorDouble::push_back(double num)
{
    if(count==max_count)
    {
        resize();
    }
    dArray[count] = num;
    count++;
}
// Resizes the array to be double the original max_count
void VectorDouble::resize(void)
{
    double *p = new double[max_count*2];
    for(int i = 0; i < count; i++)
    {
        p[i] = dArray[i];
    }
    dArray = p;
    max_count*=2;
    delete p;
}


// Returns element at specified index
double VectorDouble::getElementAt(int i) const
{
    return dArray[i];
}


// Requests that the capacity of the allocated storage space for the elements of the vector container be at least enough to hold n elements
void VectorDouble::reserve(int n)
{
    while(n<max_count)
        resize();
}


// Sets every element to 0
void VectorDouble::clear(void)
{
    for(int i = 0; i < max_count; i++)
        dArray[i] = 0;
}

Any help would be much appreciated...

任何帮助将非常感激...

回答by Omnifarious

You should include "VectorDouble.h"and not "VectorDouble.cpp"in Main.cpp.

你应该包括"VectorDouble.h"而不是"VectorDouble.cpp"Main.cpp.

The whole concept of include files is rather broken in C++ as compared to many other languages.

与许多其他语言相比,C++ 中包含文件的整个概念相当混乱。

First C++ divides things up into 'declarations' and 'definitions'. You may only ever have one definition of something in a program, but as many declarations as you want. In your VectorDouble.cppfile you are defining things, and in VectorDouble.hfile you are declaring things.

首先,C++ 将事物分为“声明”和“定义”。在一个程序中,您可能只有一个定义,但可以有任意多的声明。在您的VectorDouble.cpp文件中,您正在定义事物,而在VectorDouble.h文件中,您正在声明事物。

The #includedirective in C++ is dead simple and stupid. When it is encountered the compiler effectively does a simple textual replacement. The #includedirective is replaced with the contents of the file you are including.

#includeC++ 中的指令非常简单和愚蠢。当遇到它时,编译器会有效地进行简单的文本替换。该#include指令将替换为您包含的文件的内容。

When you #includea file of definitions, that means you effectively define them all right there where you've done the #include. This is why you shouldn't be including "VectorDouble.cpp". Since you likely also compile that file as a separate file, you then end up with at least two copies of all the definitions right there.

当您创建#include一个定义文件时,这意味着您在完成#include. 这就是为什么你不应该包括"VectorDouble.cpp". 由于您可能还将该文件编译为一个单独的文件,因此您最终会得到所有定义的至少两个副本。

This whole declaration vs. definition dichotomy gets very confusing when talking about certain kinds of things. For example, if a function is declared inlinethe function body isn't really considered a definitionanymore, exactly. This means you can have as many copies of a function body that's been declared inlineas you want. All that's required is that all of the definitions be identical.

在谈论某些类型的事情时,整个声明与定义的二分法会变得非常混乱。例如,如果声明inline了一个函数,那么函数体就不再被真正视为 adefinition了。这意味着您可以根据需要拥有已声明的函数体的多个副本inline。所需要的只是所有定义都相同。

Similarly, declaring a template function is a declaration, even if you include a function body. This is because the declaration results in no code being generated, only the template instantiation results in code generation. And that's the real litmus test for deciding if something is a declaration or definition. If it results in space being allocated or actual code being produced right then and there, then its a definition, otherwise its a declaration.

同样,声明一个模板函数也是一个声明,即使你包含了一个函数体。这是因为声明不会生成任何代码,只有模板实例化会导致代码生成。这是决定某事是声明还是定义的真正试金石。如果它导致分配空间或立即生成实际代码,则它是一个定义,否则它是一个声明。

回答by templatetypedef

The error you're getting is a linker error telling you that the compiler is finding multiple definitions for certain member functions. If you look at this chunk of the error message:

您收到的错误是链接器错误,告诉您编译器正在为某些成员函数查找多个定义。如果您查看此错误消息块:

public: __thiscall VectorDouble::VectorDouble(void)" (??0VectorDouble@@QAE@XZ) already defined in Main.obj

You can see buried in there the fact that it's talking about the constructor VectorDouble::VectorDouble()already being defined.

您可以看到隐藏在其中的事实是它在谈论VectorDouble::VectorDouble()已经定义的构造函数。

I think the particular problem you're running into is in this line in main.cpp:

我认为您遇到的特定问题是 main.cpp 中的这一行:

#include "VectorDouble.cpp"

The problem is that this includes the sourcefile, not the headerfile. Consequently, when you compile main.cpp, you'll be compiling all of main, plus all of the definitions in VectorDouble.cpp. When the linker then tries linking this with the object file generated when it compiled VectorDouble.cpp, it will find two definitions of everything - one from VectorDouble.cpp and one from main.cpp.

问题是这包括文件,而不是文件。因此,当您编译 main.cpp 时,您将编译所有 main 以及 VectorDouble.cpp 中的所有定义。当链接器尝试将其与编译 VectorDouble.cpp 时生成的目标文件链接时,它将找到所有内容的两个定义 - 一个来自 VectorDouble.cpp,一个来自 main.cpp。

To fix this, change this line to read

要解决此问题,请将此行更改为阅读

#include "VectorDouble.h"

That should resolve your issue. More generally, though, it's extremely rare to actually #includea .cpp file. You almost always include headers, not sources.

那应该可以解决您的问题。不过,更一般地说,实际上#include是 .cpp 文件是极其罕见的。您几乎总是包含标题,而不是来源。

Hope this helps!

希望这可以帮助!

回答by dfan

Main.cpp shouldn't be #include-ing VectorDouble.cpp; it should #includeVectorDouble.h. If you are linking both .cpp files, the linker is seeing everything in VectorDouble.cpp twice (once on its own, and once when it's #include-d from Main.cpp).

Main.cpp 不应该是#include-ing VectorDouble.cpp;它应该是#includeVectorDouble.h。如果您同时链接两个 .cpp 文件,则链接器会看到 VectorDouble.cpp 中的所有内容两次(一次是单独的,一次是在#includeMain.cpp 中的-d 时)。

回答by Penny

I got a similar link error when I tried to define a class in a separate file named PresentDataStruct.hand also created a PresentDataStruct.cppfile.

当我尝试在名为PresentDataStruct.h的单独文件中定义一个类并创建一个PresentDataStruct.cpp文件时,我遇到了类似的链接错误。

Here are the contents of PresentDataStruct.h:

以下是PresentDataStruct.h的内容:

#pragma once

#include <string>
using namespace System;
ref class CPresentDataStruct
{
public:
    CPresentDataStruct();
    ~CPresentDataStruct();

public:
    void SomeActionOnData();

public:

    System::String^ Name;
    DateTime^ BirthDay;

};

void CPresentDataStruct::SomeActionOnData()
{
    //TO DO here
}

CPresentDataStruct::CPresentDataStruct()
{
}

CPresentDataStruct::~CPresentDataStruct()
{
}

While in PresentDataStruct.cppit has one line:

而在PresentDataStruct.cpp 中,它只有一行:

include "PresentDataStruct.h"

Then the link error appears when I add include "PresentDataStruct.h"to the maindialog.hfile.

然后当我添加include "PresentDataStruct.h"maindialog.h文件时出现链接错误。

So I moved this to PresentDataStruct.cppfile and the link error disappeared:

所以我把它移到PresentDataStruct.cpp文件,链接错误消失了:

void CPresentDataStruct::SomeActionOnData()
{
    //TO DO here
}

CPresentDataStruct::CPresentDataStruct()
{
}

CPresentDataStruct::~CPresentDataStruct()
{
}