【问题标题】:What is causing the LNK2005?是什么导致了 LNK2005?
【发布时间】:2015-04-13 09:29:51
【问题描述】:

如果我将实现留在头文件 d_date.h 中,则以下程序可以正常运行,但是,我需要通过源 d_date.cpp 来实现它。所有重载都可以正常工作,但由于某种原因存在链接器错误。它可能与我的预处理器指令有关,但我似乎无法弄清楚。

主要来源

// File: Driver.cpp
// Note: Used to test our date class with overloaded functions

#include <iostream>
#include "d_date.h"

using namespace std;

bool operator ==(date, date);
bool operator !=(date, date);

void main (void)
{
date date1;
date date2;

cout << "Enter date1 and date2:" << endl;


while (cin >> date1 >> date2)
{
    cout << "Printing date1 and date2" << endl;
    cout << date1 << endl << date2 << endl;

    if (date1 == date2) 
        cout << date1 << " is equal to " << date2 << endl;

    if (date1 != date2) 
        cout << date1 << " is not equal to " << date2 << endl;

    if (date1 < date2) 
        cout << date1 << " is less than " << date2 << endl;

    if (date1 > date2) 
        cout << date1 << " is greater than " << date2 << endl;

    ++date1;
    ++date2;


    cout << "Increment of date1: " << date1 << endl;
    cout << "Increment of date2: " << date2 << endl;

    cout << endl << "---End of Run---" << endl << endl;

    cout << "Enter date1 and date2:" << endl; 
}
}

bool operator ==(date lhs, date rhs)
{
return (lhs.getYear() == rhs.getYear() &&
    lhs.getMonth() == rhs.getMonth() &&
    lhs.getDay() == rhs.getDay());
}

bool operator !=(date lhs, date rhs)
{
   return !(lhs == rhs);
}

类头

//d_date.h
#ifndef DATE_CLASS
#define DATE_CLASS

#include <iostream>
#include <iomanip>
#include <string>

#include "d_except.h"

using namespace std;

class date
{
public:
  date (int mm=1, int dd=1, int yyyy=1900);
        // supply date in format MM/DD/YYYY
        // preconditions: 1 <= mm <= 12,
        //                1 <= dd <= daysInMonth()

  void writeShortDate () const;
        // output the date in the format "MM/DD/YYYY"
  void writeLongDate () const;
        // output the date in the format "month day, year"

  void incrementDate(int ndays);
        // add ndays days to the date
        // precondition: 0 <= ndays <= 365

  int numberOfDays() const;
        // return the number of days into the year

  int getMonth() const;
        // return the month as integer value 1 to 12
  int getDay() const;
        // return day of the month
  int getYear() const;
        // return the year

  void setMonth(int mm);
        // update the month
        // precondition: 1 <= mm <= 12
  void setDay(int dd);
        // update the day
        // precondition: 1 <= dd <= daysInMonth()
  void setYear(int yyyy);
        // update the year
        // precondition:  if the date is February 29,
        //                yyyy must be a leap year
  int daysInMonth() const;
        // return number of days in the month

  bool isLeapYear() const;
        // is the current year a leap year (true/false)

  bool operator >(date);
  bool operator <(date);

  date operator ++();
  date operator ++(int);

  friend istream& operator >> (istream& , date& );
  friend ostream& operator << (ostream& , date );


private:
  enum monthName {Jan = 1, Feb, Mar, Apr, May, Jun,
                  Jul, Aug, Sep, Oct, Nov, Dec};
        // private type used by date

  int month, day, year;
        // private members that specify the date

};

我没有包含标题的其余部分,因为它是一堆函数,而且有点长。

这是重载函数的实现

//implementation of member overload operators
//d_date.cpp
#include "d_date.h"
#include <iostream>
#include <cassert>

using namespace std;

istream& operator >> (istream& istr, date& rhs)
{
char temp;
int m, d, y;

istr >> m >> temp >> d >> temp >> y;

rhs.setMonth(m);
rhs.setDay(d);
rhs.setYear(y);

return istr;
}

ostream& operator << (ostream& ostr, date rhs)
{
ostr << rhs.month << "/" << rhs.day << "/" << rhs.year;
return ostr;
}

date date::operator ++()
{
this->incrementDate(1);
return *this;
}

date date ::operator++(int)
{
date temp = *this;

this->incrementDate(1);

return temp;
}

bool date::operator >(date rhs)
{
if (this->year > rhs.year)
    return true;
else if (this->year == rhs.year)
    return this->numberOfDays() > rhs.numberOfDays();
else
    return false;
}

bool date::operator <(date rhs)
{
if (this->year < rhs.year)
    return true;
else if (this->year == rhs.year)
    return this->numberOfDays() < rhs.numberOfDays();
else
    return false;

}

【问题讨论】:

  • 你编译both文件吗?和link两个生成的目标文件在一起?
  • 是的,所有东西都是一起编译的。错误是 LNK2005 i.imgur.com/7IAd7l1.jpg 当函数仅被放入 .cpp 并且没有在标题中使用时,它一切正常,但是我不确定我是否可以这样做。标题是预先构建的,我的工作是修改它并添加重载运算符
  • 您是否使用#include 指令来包含源文件?头文件中有非内联函数定义吗?
  • 是的,如果你看上面的话,我发布了 3 个文件,不包括我不能修改的第四个异常文件,它只被 d_date.h 使用,它是我显示的标题.据我所知,没有内联
  • 你在 Visual Studio 中运行吗?

标签: c++ c-preprocessor linker-errors preprocessor-directive


【解决方案1】:

我的猜测是问题出在头文件中的“里面有一堆函数”。

如果将函数定义放在头文件中,它将在包含头文件的所有translation units(即源文件)中定义。

基本上有三种方法可以解决这个问题:

  1. 使用链接说明符关键字inline 使函数内联,例如

    inline int date::daysInMonth() const {
        ...
    }
    
  2. 使函数定义内联在类规范中,例如

    class date {
        ...
        int daysInMonth() const {
            ...
        }
        ...
    };
    
  3. 从头文件中移动定义,并将它们放入源文件中。

【讨论】:

  • 我认为最简单的可能就是将所有定义移动到源中,因为我已经对其进行了测试并且它可以工作。希望老师允许哈哈!