为什么我会收到这些"已经定义"的链接器错误?

Som*_*ive 6 c++ linker

我是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
....    
Run Code Online (Sandbox Code Playgroud)

还有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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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);
};
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

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

Omn*_*ous 28

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

与许多其他语言相比,包含文件的整个概念在C++中相当破碎.

首先,C++将事物分为"声明"和"定义".你可能只对程序中的某个东西有一个定义,但是你想要的声明数量很多.在您的VectorDouble.cpp文件中,您正在定义事物,并且在VectorDouble.h文件中您正在声明事物.

#includeC++中的指令简单而愚蠢.遇到这种情况时,编译器会有效地进行简单的文本替换.该#include指令将替换为您包含的文件的内容.

如果你#include是一个定义文件,这意味着你可以在那里完全定义它们#include.这就是你不应该包括的原因"VectorDouble.cpp".由于您可能还将该文件编译为单独的文件,因此您最终会得到至少两个所有定义的副本.

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

同样,即使包含函数体,声明模板函数也是一个声明.这是因为声明导致没有生成代码,只有模板实例化导致代码生成.这就是决定某件事是宣言还是定义的真正试金石.如果它导致分配空间或者正确生成实际代码,那么它就是一个定义,否则就是一个声明.


tem*_*def 6

您收到的错误是链接器错误,告诉您编译器正在为某些成员函数找到多个定义.如果你看一下这个错误信息的大块:

public: __thiscall VectorDouble::VectorDouble(void)" (??0VectorDouble@@QAE@XZ) already defined in Main.obj
Run Code Online (Sandbox Code Playgroud)

你可以看到埋藏在那里的事实是它正在讨论VectorDouble::VectorDouble()已经定义的构造函数.

我认为你遇到的特殊问题是在main.cpp的这一行:

#include "VectorDouble.cpp"
Run Code Online (Sandbox Code Playgroud)

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

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

#include "VectorDouble.h"
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助!