Ошибка компиляции 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)
которые не одинаковы...