已定义的Obj?链接错误?

6
我真的无法理解为什么我会遇到这些错误,尤其是当我有包含保护时。以下是我的错误信息(请忽略我电脑的名称):
1> main.obj: error LNK2005:“class std :: basic_ostream >&__cdecl operator <<(class std :: basic_ostream >&,class Date&)”(?? 6@YAAAV?$ Basic_ostream @ DU?$ Char_traits @ D @ std @@ @ std @@ AAAV01 @ AAPAVDate @@ @ Z)已在loan.obj中定义。
1> main.obj: error LNK2005:“class std :: basic_ostream >&__cdecl operator <<(class std :: basic_ostream >&,class Loan&)”(?? 6@YAAAV?$ Basic_ostream @ DU?$ Char_traits @ D @ std @@ @ std @@ AAAV01 @ AAPAVLoan @@ @ Z)已在loan.obj中定义。
1> C:\ Users \ SweetAssSarah \ Documents \ Visual Studio 2012 \ Projects \ ConsoleApplication4 \ Debug \ a1.exe:致命错误LNK1169:找到一个或多个重复定义的符号。
这是我的四个文件: Main.cpp:
#ifndef _main_cpp
#define _main_cpp

#include<iostream>
#include "loan.h"
#include "date.h"

using namespace std;

void main(){
    const int MAX_SIZE = 80;
    char response[MAX_SIZE];

    Loan sarah("Sarah", "123 Awesomeville ", Date (01,February,2010));

    cout << sarah.getName() << " address: " << sarah.getAddress() << endl;
    cout << "Date: " << sarah.getDate() << endl;

    //keep console open until user types a key and enter
    cout <<"\n\n" << "Press ENTER to continue";
    cin.getline(response, MAX_SIZE);

    return;
}    
#endif

loan.cpp:

#ifndef _loan_cpp
#define _loan_cpp

#include <iostream>
#include "loan.h"
#include "date.h"

using namespace std;

Loan::Loan(char * aName, char * anAddress, Date aDate){
    name = aName;
    address = anAddress;
    date = aDate;
    cout <<"CONSTRUCTING: " << name << "\n"; 
}    
Loan::~Loan(){
    cout << "DESTRUCTING: " << name << endl;
} 
char * Loan::getName() {return  name;} 
char * Loan::getAddress(){return address;} 
Date Loan::getDate(){return date;}

void Loan:: printOn(ostream & ostr) {
    cout << name << " address: " << address << endl;
}    
#endif

loan.h:

#ifndef _loan_h
#define _loan_h

#include <math.h> //for the pow() function to do exponentiation
#include <iostream>
#include "date.h"

using namespace std;

class Loan{
public:
    Loan(char *, char *, Date );//constructor
    ~Loan();

    char * getName();
    char * getAddress();
    Date getDate();

    void printOn(ostream & ostr);
private: 
    char * name; 
    char * address;
    Date date; //requires class Date to have a default constructor

};
ostream & operator<<(ostream & ostr, Loan & aLoan) { 
    aLoan.printOn(ostr); 
    return ostr; 
}
#endif

date.h:

#ifndef _date_h
#define _date_h
#include <iostream>

enum Month {January=1, February, March, April, May, June, July, August,
September, October, November, December};

using namespace std;

class Date{
public:
//  Date() {};
    Date(int aDay = 1, Month aMonth = May, int aYear = 2005){
        day = aDay;
        month = aMonth;
        year = aYear;
}    
void printOn(ostream & o){
    o << day << "/" << month << "/" << year;
}
private:
    int day;
    Month month;
    int year;
};    
ostream & operator<<(ostream & ostr, Date & d) { 
    d.printOn(ostr); 
    return ostr; 
} 
#endif

Please help!


2
只需在您的operator<<()定义前面加上inline,以便多个定义不会生成该错误。 - Hans Passant
1
我从未听说过inline - 非常感谢你向我介绍它! - Sarah
inline 对我有用(在 cpp 中)。仍在考虑为什么。 - Richard Peck
可能是重复的问题:error LNK2005: already defined - C++ - JaMiT
1个回答

16

如评论中已经说明的那样,<< 运算符需要被内联或在 cpp 文件中定义。当你在头文件中定义函数时,它将会在每个包含该头文件的 cpp 文件中被编译。如果你在多个 cpp 文件中包含该头文件,则会产生编译器错误,因为相同的代码将会被编译成多个 .obj 文件。链接器不知道使用哪个 .obj 文件并会抛出错误。

解决方案1 - 拆分为 .h 和 .cpp 文件

loan.h

ostream & operator<<(ostream & ostr, Loan & aLoan);

贷款.cpp

ostream & operator<<(ostream & ostr, Loan & aLoan) { 
    aLoan.printOn(ostr); 
    return ostr; 
}

解决方案2 - 内联

loan.h

inline ostream & operator<<(ostream & ostr, Loan & aLoan) { 
    aLoan.printOn(ostr); 
    return ostr; 
}

第二种解决方案会导致编译器通过将函数代码内联到每个调用发生的代码位置来解析函数调用。这会导致编译后的代码中存在冗余,并且应该避免在大型函数中使用。

解决方案三 - 静态

loan.h

static ostream & operator<<(ostream & ostr, Loan & aLoan) { 
    aLoan.printOn(ostr); 
    return ostr; 
}

将函数声明为static后,它具有内部链接性。但编译器是否对其进行内联仍然由编译器决定。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接