2011-03-17 74 views
5

我是C++的初学者,但我有一些使用Java的经验。我收到一些我不明白的错误。我附上了错误控制台的图片和它下面的代码。为什么我得到这些'已经定义'的链接器错误?

Error 1 error LNK2005: "public: __thiscall VectorDouble::VectorDouble(void)" ([email protected]@[email protected]) 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)" ([email protected]@[email protected]@Z) already defined in Main.obj C:\Users\carrea\Code\Visual Studio\COMP201\Lab8_VectorDoubleClass\VectorDouble.obj Lab8_VectorDoubleClass 
....  

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


#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


#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; 
} 

任何帮助,将不胜感激......

+8

你不应该#包括“VectorDouble.h”? – 2011-03-17 00:20:17

+0

转到CodeReview.SE? – 2011-03-17 00:21:19

+0

复制分配没有正确实现('void operator =(const VectorDouble&RIGHT_SIDE);')。一般来说,它应该返回一个参考。 – Mahesh 2011-03-17 00:27:36

回答

26

您应该在Main.cpp中包含"VectorDouble.h"而不是"VectorDouble.cpp"

与许多其他语言相比,包含文件的整个概念在C++中相当破碎。第一个C++将事物分成'声明'和'定义'。你可能只有一个程序中的某个定义,但只要你想要的声明。在你的VectorDouble.cpp文件中你正在定义的东西,并在VectorDouble.h文件中声明的东西。

C++中的#include指令简直太愚蠢了。遇到它时,编译器会有效地进行简单的文本替换。 #include指令被替换为您所包含文件的内容。

当你有一个定义的文件,这意味着你有效地定义它们在那里你已经完成了#include。这就是为什么你不应该包括"VectorDouble.cpp"。由于您可能还会将该文件作为单独的文件进行编译,因此您至少会在这里得到至少两个所有定义的副本。

整个声明与定义二分法在讨论某些事物时变得非常混乱。例如,如果一个函数被声明为inline,那么函数体不再被认为是definition。这意味着您可以拥有任意数量的已声明为inline的函数体副本。所有需要的是所有的定义都是相同的。

同样,即使包含函数体,声明模板函数也是声明。这是因为声明导致没有生成代码,只有模板实例化导致代码生成。这是决定是否有声明或定义的真正考验。如果它导致分配空间或实际编码正确,那么它就是一个定义,否则它就是一个声明。

6

你得到的错误是连接错误,告诉你,编译器是找到多个定义某些成员功能。如果你看一下这个块的错误消息:

public: __thiscall VectorDouble::VectorDouble(void)" ([email protected]@[email protected]) already defined in Main.obj 

你可以看到埋在那里的事实,它在谈论已经被定义构造函数VectorDouble::VectorDouble()

我认为你正在运行到特定的问题是在这条线在main.cpp中:

#include "VectorDouble.cpp" 

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

为了解决这个问题,更改此行以读取

#include "VectorDouble.h" 

这应该解决您的问题。但更普遍的是,实际上#include a .cpp文件非常罕见。你几乎总是包含标题,而不是来源。

希望这会有所帮助!

+1

我不认为这是一个非常好的答案(虽然不是-1),因为它不能解释为什么有'源'文件和'头'文件。这是一个非常古怪的区别,在现代常用语言中大多只存在于C和C++中。它值得解释,特别是对于一个Java程序员来说。 – Omnifarious 2011-03-17 04:16:24

+0

这不是一个奇怪的区别,并以某种形式出现在用于大规模编程的所有语言中。您通常希望将实现中指定的接口保存在单独的文件中。 – 2011-03-17 11:36:00

+0

@James Kanze:它不存在于Java中,也不存在于Python,Ruby,perl,PHP或lisp,erlang或OCaml中。事实上,在过去10年里我用过的所有语言都是严肃认真的语言,而C和C++是唯一有这种区别的语言。 – Omnifarious 2011-03-17 18:01:54

1

Main.cpp不应该是#include -ing VectorDouble.cpp;它应该是#include VectorDouble.h。如果您链接了两个.cpp文件,链接器将在VectorDouble.cpp中看到所有内容(一次是自己的,一次是从Main.cpp发出的#include -d)。

0

我有一个类似的链接错误,当我试图在一个名为PresentDataStruct.h一个单独的文件来定义一个类,还创建了一个PresentDataStruct.cpp文件。

这里是内容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() 
{ 
} 

虽然PresentDataStruct.cpp有一行:

include "PresentDataStruct.h" 

后来,当我加入include "PresentDataStruct.h"出现链接错误 到maindialog.h文件。

所以我搬到这PresentDataStruct.cpp文件和链接错误消失:在main.cpp中,而不是“VectorDouble.cpp”

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

CPresentDataStruct::CPresentDataStruct() 
{ 
} 

CPresentDataStruct::~CPresentDataStruct() 
{ 
} 
相关问题