Ошибка компиляции C++ с оператором >>

Я сейчас пишу программу. Один из моих тестов не проходит, когда я пытаюсь проверить свои конструкторы. Я получаю это сообщение ниже как ошибку. Я попробовал оба терминала VS:Community 2017 и Linux, но оба не дают мне достаточно информации для устранения проблемы. Может ли кто-нибудь указать мне, где я должен смотреть? В соответствии с g++ я думаю, что что- то не так с оператором >> но idk, что делать.

Терминал Linux g++

/tmp/cc2iecjr.o:test3.cpp:(.text+0x289): undefined reference to `ict::operator>>(std::istream&, ict::Date const&)'
/tmp/cc2iecjr.o:test3.cpp:(.text+0x289): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `ict::operator>>(std::istream&, ict::Date const&)'
/tmp/cc2iecjr.o:test3.cpp:(.text+0x3bf): undefined reference to `ict::operator>>(std::istream&, ict::Date const&)'
/tmp/cc2iecjr.o:test3.cpp:(.text+0x3bf): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `ict::operator>>(std::istream&, ict::Date const&)'
/tmp/cc2iecjr.o:test3.cpp:(.text+0x4f2): undefined reference to `ict::operator>>(std::istream&, ict::Date const&)'
/tmp/cc2iecjr.o:test3.cpp:(.text+0x4f2): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `ict::operator>>(std::istream&, ict::Date const&)'
collect2: error: ld returned 1 exit status

Visual Studio 2017

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2019 unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl ict::operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class ict::Date const &)" (??5ict@@YAAEAV?$basic_istream@DU?$char_traits@D@std@@@std@@AEAV12@AEBVDate@0@@Z) referenced in function main Milestone1  C:\Users\Anthony Elistratov\Documents\cPlusPlusCodeSnippets\OOP244\Final Project\Milestone1\Milestone1\02-ConstructorTester.obj 1   

test3.cpp

//test3.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include "Date.h"
#include "POS.h"
using namespace std;
using namespace ict;

bool equalDates(const Date& A, const Date& B);
bool yes();
int main(){
  int ret = 0;
  bool ok = true;
  if (ok){
     cout << "Testing Date constructors and operator<< overload; " << endl;
    time_t t = time(NULL);
    Date Cur;
    tm lt = *localtime(&t);
    Date tCur(lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min);
    cout << tCur << (equalDates(tCur, Cur) ? " is the same as " : " is not the same as ") << Cur << endl;

    if (equalDates(tCur, Cur)){
       cout << "Passed!" << endl;
    }
    else{
       cout << "One or more of the Date constructors or operator<< are not implemented correctly." << endl;
       ok = false;
    }
  }
  if (ok){
    Date A(2018, 10, 18);
    Date B = A;
    cout << "Testing Date(int, int, int) constructor and operator>> overload; " << endl;
    cout << "enter the following date, 2018/10/18" << endl << ">";
    cin >> B;

    if (!equalDates(A, B)){
      cout << "Either the constructor or operator>> is not implemented correctly." << endl;
      ok = false;
    }
    else{
      cout << "Passed!" << endl;
    }
  }
  if (ok){
    Date A(2015, 9, 7, 14, 30);
    Date B = A;
    B.dateOnly(false);
    cout << "Testing Date(int, int, int,int,int) constructor and operator>> overload; " << endl;
    cout << "enter the following date, 2015/9/7, 14:30" << endl << ">";
    cin >> B;

    if (!equalDates(A, B)){
      cout << "Either the constructor or operator>> is not implemented correctly." << endl;
      ok = false;
    }
    else{
      cout << "Passed!" << endl;
    }
  }
  if (ok){
    Date A(2015, 9, 7, 15);
    Date B = A;
    B.dateOnly(false);
    cout << "Testing Date(int, int, int,int,int=0) constructor and operator>> overload; " << endl;
    cout << "enter the following date, 2015/9/7, 15:0" << endl << ">";
    cin >> B;

    if (!equalDates(A, B)){
      cout << "Either the constructor or operator>> is not implemented correctly." << endl;
      ok = false;
    }
    else{
      cout << "Passed!" << endl;
    }
  }
  if (ok){
    cout << "You passed all Constructor tests, run test no 3!" << endl;
  }
  else{
    cout << "You did not pass all the tests, keep working on your project!" << endl;
    ret = 1;
  }


  return ret;
}
bool equalDates(const Date& A, const Date& B) {
   ostringstream Astr, Bstr;
   Astr << A;
   Bstr << B;
   return (Astr.str() ==  Bstr.str());
}

bool yes(){
  char ch;
  ch = cin.get();
  cin.ignore(1000, '\n');
  return ch == 'y' || ch == 'Y';
}

Date.h

//Date.h
// compilation safegaurds
#ifndef ICT_DATE_H_
#define ICT_DATE_H_

#include <iostream>
//ict namespace 
namespace ict {
   //Date defined Error values
    const int NO_ERROR = 0;//No error - the date is valid
    const int CIN_FAILED = 1;//istream failed on accepting information using cin
    const int YEAR_ERROR = 2;//Year value is invalid
    const int MON_ERROR = 3;//Month value is invalid
    const int DAY_ERROR = 4;//Day value is invalid
    const int HOUR_ERROR = 5;//Hour value is invalid
    const int MIN_ERROR = 6;//Minute value is invalid

    class Date {
    private:
        //member variables
        int m_year;//Year; a four digit integer between MIN_YEAR and MAX_YEAR, as defined in “POS.h”   
        int m_mon;//Month of the year, between 1 to 12
        int m_day;//Day of the month, note that in a leap year February has 29 days, (see mday() member function)
        int m_hour;//A two digit integer between 0 and 23 for the hour the a day.
        int m_min;//A two digit integer between 0 and 59 for the minutes passed the hour
        int m_readErrorCode;
        bool m_dateOnly;//A flag that is true if the object is to only hold the date and not the time. In this case the values for hour and minute are zero. 

        //private methods
        int value()const;
        void errCode(int errorCode);
        void set(int year, int mon, int day, int hour, int min);//Sets the member variables to the corresponding arguments and then sets the m_readErrorCode to NO_ERROR.
    public:
        //constructors
        Date();
        Date(int year, int mon, int day); //m_dateOnly = true
        Date(int year, int mon, int day, int hour, int min = 0);//m_dateOnly = false //m_readErrorCode = no error


        void set();



        //operator ovrloads
        bool operator==(const Date& D)const;
        bool operator!=(const Date& D)const;
        bool operator<(const Date& D)const;
        bool operator>(const Date& D)const;
        bool operator<=(const Date& D)const;
        bool operator>=(const Date& D)const;

        //methods
        int errCode()const;//Returns the m_readErrorCode value.
        bool bad()const;//Returns true if m_readErrorCode is not equal to zero.
        bool dateOnly()const;//Returns the m_dateOnly attribute.
        void dateOnly(bool value);//Sets the m_dateOnly attribute to the “value” argument.Also if the “value” is true, then it will set m_hour and m_min to zero.


        int mdays()const;

        //istream  and ostream read and write methods
        std::istream& read(std::istream& is = std::cin);
        std::ostream& write(std::ostream& ostr = std::cout)const;
   };
   // operator<< and >> overload prototypes for cout and cin
    std::istream& operator>>(std::istream& is, const Date& D);
    std::ostream& operator<<(std::ostream& ostr, const Date& D);

}
#endif//ICT_DATE_H_

Date.cpp

//Date.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iomanip>
#include <iostream>
#include <ctime>
using namespace std;
#include "Date.h"
#include "POS.h"


namespace ict{
  void Date::set(){
    time_t t = time(NULL);
    tm lt = *localtime(&t);
    m_day = lt.tm_mday;
    m_mon = lt.tm_mon + 1;
    m_year = lt.tm_year + 1900;
    if (dateOnly()){
      m_hour = m_min = 0;
    }
    else{
      m_hour = lt.tm_hour;
      m_min = lt.tm_min;
    }
  }

  int Date::value()const{
    return m_year * 535680 + m_mon * 44640 + m_day * 1440 + m_hour * 60 + m_min;
  }

  int Date::mdays()const{
    int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, -1 };
    int mon = m_mon >= 1 && m_mon <= 12 ? m_mon : 13;
    mon--;
    return days[mon] + int((mon == 1)*((m_year % 4 == 0) && (m_year % 100 != 0)) || (m_year % 400 == 0));
  }

  //no argument constructor
  Date::Date() {
      m_dateOnly = false;
      set();
  }
  //3 argument constructor
  Date::Date(int year, int mon, int day) {
      m_dateOnly = true;
      //setting variables;
      m_year = year;
      m_mon = mon;
      m_day = day;
      //not going to be displayed
      m_hour = 0;
      m_min = 0;

      //error code
      m_readErrorCode = 0;
  }
  //5 argument constructor added
  Date::Date(int year, int mon, int day, int hour, int min ) {
      m_dateOnly = false;

      //setting variables
      m_year = year;
      m_mon = mon;
      m_day = day;
      m_hour = hour;
      m_min = min;

      //error code
      m_readErrorCode = 0;
  }
  //void @errCode(int errorCode);
  //Sets the m_readErrorCode member variable to one of the possible values listed above.
  void Date::errCode(int errorCode) {
      m_readErrorCode = errorCode;
  }

  //void @set(int year, int mon, int day, int hour, int min)
  //Sets the member variables to the corresponding arguments and then sets the m_readErrorCode to NO_ERROR.
  void Date::set(int year, int mon, int day, int hour, int min) {

      //setting variables
      m_year = year;
      m_mon = mon;
      m_day = day; 
      m_hour = hour;
      m_min = min;

      //error code
      m_readErrorCode = NO_ERROR;
  }

  //Public member-functions (methods) and operators
  //
  bool Date::operator==(const Date& D)const {
      return (this->value() == D.value());
  }
  bool Date::operator!=(const Date& D)const {
      return (this->value() != D.value());
  }
  bool Date::operator<(const Date& D)const {
      return (this->value() < D.value());
  }
  bool Date::operator>(const Date& D)const {
      return (this->value() > D.value());
  }
  bool Date::operator<=(const Date& D)const {
      return (this->value() <= D.value());
  }
  bool Date::operator>=(const Date& D)const {
      return (this->value() >= D.value());
  }

  //Accessor or getter member functions (methods):
  //Returns the m_readErrorCode value.
  int Date::errCode()const {
      return m_readErrorCode;
  }
  //Returns true if m_readErrorCode is not equal to zero.
  bool Date::bad()const {
      bool error;

      if (m_readErrorCode != 0) {
          error = true;
      }
      else {
          error = false;
      }

      return error;
  }
  //Returns the m_dateOnly attribute.
  bool Date::dateOnly()const {
      return m_dateOnly;
  }
  //Sets the m_dateOnly attribute to the “value” argument.Also if the “value” is true, then it will set m_hour and m_min to zero.
  void Date::dateOnly(bool value) {
      m_dateOnly = value;

      if (m_dateOnly) {
          m_hour = 0;
          m_min = 0;
      }
  }

  //istream  and ostream read and write methods
  //Reads the date in the following format: YYYY/MM/DD (e.g. 2015/03/24) from the console if _date only is true
  std::istream& Date::read(std::istream& is) {
      is >> m_year;
      if (is.get() != '/') {
          m_readErrorCode = CIN_FAILED;
          return is;
      }
      is >> m_mon;
      if (is.get() != '/') {
          m_readErrorCode = CIN_FAILED;
          return is;
      }
      is >> m_readErrorCode;
      //validate
      return is;
  }

  std::ostream& Date::write(std::ostream& ostr)const {
      if (m_dateOnly) {
          ostr << m_year << "/" << m_mon << "/" << m_day;
      }
      else {
          ostr << m_year << "/" << m_mon << "/" << m_day << ", " << m_hour << ":" << m_min;
      }
      return ostr;
  }

  //helpers
  std::istream& operator>>(std::istream& is, Date& D) {
      return D.read(is);
  }
  std::ostream& operator<<(std::ostream& ostr, const Date& D) {
      return D.write(ostr);
  }


}

error.h

//Error.h
    // compilation safegaurds
#ifndef ICT_ERROR_H_
#define ICT_ERROR_H_

#include <iostream>
namespace ict {
   class Error {
      char* m_message;
   public:
   // constructors
       //Sets the m_message member variable to nullptr.
       Error();
       //Sets the m_message member variable to nullptr and then uses the message() setter member function to set the error message to the errorMessage argument.
       Error(const char* errorMessage);
       //A deleted copy constructor to prevent an Error object to be copied.
       Error(const Error& em) = delete; //no implementation needed
   // destructor

   // deleted constructor and operator=
       //A deleted assignment operator overload to prevent an Error object to be assigned to another.
       Error& operator=(const Error& em) = delete;//no implementation needed
   // operator= for c-style strings
       void operator=(const char* errorMessage);
   // methods
       virtual ~Error(){ delete [] m_message; m_message = nullptr;};
       void clear();
       bool isClear()const;
       void message(const char* value);
       operator const char*() const;
       operator bool()const;
   // cast overloads

   };
   // operator << overload prototype for cout

   std::ostream& operator<<(std::ostream& ostr, const Error& em);
}
#endif //ICT_ERROR_H_

Error.cpp

//Error.cpp

#define _CRT_SECURE_NO_WARNINGS 

#include "Error.h"
#include <cstring>

namespace ict{
    Error::Error() {
        m_message = nullptr;
    }

    Error::Error(const char* errorMessage) {
        m_message = nullptr;
        message(errorMessage);
    }

    //have a look
    void Error::operator=(const char* errorMessage) {
        clear();//dealloc m_message
        message(errorMessage);
    }

    void Error::clear() {
        delete[] m_message;
        m_message = nullptr;

    }


    bool Error::isClear()const {
        bool clear;
        if (m_message == nullptr) {
            clear = true;
        }
        else {
            clear = false;
        }

        return clear;
    }

    void Error::message(const char* value) {
        clear();//dealloc m_message
        m_message = new char[strlen(value + 1)];
        strcpy(m_message, value);
    }

    Error::operator const char*() const {
        return m_message;
    }

    Error::operator bool()const {
        return isClear();
    }

    std::ostream& operator<<(std::ostream& ostr, const Error& em) {
        //to be coded
        //do some stuff with ostr

        if (em.isClear()) {
            //nothing
        }
        else {
            ostr << "error";
        }

        return ostr;
    }

}//namespace ict

POS.h

//POS.h
// compilation safeguards
#ifndef ICT_POS_H_
#define ICT_POS_H_

// defined values
#define TAX 0.13
#define MAX_SKU_LEN 7
#define MIN_YEAR 2000
#define MAX_YEAR 2030
#define MAX_NO_ITEMS 2000

#endif//ICT_POS_H_

1 ответ

Решение

Date.h имеет объявление

std::istream& operator>>(std::istream& is, const Date& D);

в то время как Date.cpp имеет определение:

std::istream& operator>>(std::istream& is, Date& D)

которые не одинаковы...

Другие вопросы по тегам