2015-02-12 4 views
-2

Следующая программа работает очень хорошо, если я оставляю реализацию в файле заголовка d_date.h, однако мне нужно, чтобы она была реализована через источник d_date.cpp. Все перегрузки работают нормально, но по какой-то причине возникает ошибка компоновщика. Вероятно, это имеет какое-то отношение к моим директивам препроцессора, но я просто не могу понять это.Что вызывает LNK2005?

Первичный источник

// 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; 

} 
+0

Какая ошибка? –

+0

Вы компилируете * оба * файлы? И * ссылка * и сгенерированные объектные файлы вместе? –

+0

Да все скомпилировано. Ошибка LNK2005 http://i.imgur.com/7IAd7l1.jpg Все это работает, когда функции просто помещаются в .cpp исключительно и не используются в заголовке, однако я не уверен, разрешено ли мне для этого. Заголовок был предварительно сконструирован. Моя задача состояла в том, чтобы изменить его и добавить перегруженные операторы. – icesickle

ответ

0

Я думаю, что проблема заключается в «кучу функций в нем» в файле заголовка.

Если вы поместите определение функции в файл заголовка, оно будет определено во всех translation units (то есть в исходных файлах), где заголовок был включен.

Есть в основном три способа решить эту проблему:

  1. Используйте подъёмник-спецификатор ключевое слово inline сделать функцию инлайн, как, например,

    inline int date::daysInMonth() const { 
        ... 
    } 
    
  2. Сделать определения функций встроенными в спецификации класса, например,

    class date { 
        ... 
        int daysInMonth() const { 
         ... 
        } 
        ... 
    }; 
    
  3. Переместить определения из файла заголовка и поместить их в исходный файл.

+0

Я думаю, что проще всего просто переместить все определения в источник, потому что Я уже тестировал его, и он работает. Надеюсь, это разрешено моим учителем ха-ха! – icesickle