I'm in the final stages of writing a small Calendar library for a school assignment and I have run into an unexpected and very confusing problem; my assignment operator is not overridden when I introduce templates!
So the structure is the following: I have an abstract class Date
with mostly pure virtual functions (including the assignment operator), and then I have two subclasses Gregorian
and Julian
that implement all its functions. Finally, I have written a template for a class Calendar
, which contains today's date (in the form of a Gregorian
or Julian
object) and some other stuff that aren't really relevant for this particular problem.
The problem is that when trying to set this member today
I get a long linker error:
Error 4 error LNK2019: unresolved external symbol "public: virtual class lab2::Date & __thiscall lab2::Date::operator=(class lab2::Date const &)" (??4Date@lab2@@UAEAAV01@ABV01@@Z) referenced in function "public: class lab2::Gregorian & __thiscall lab2::Gregorian::operator=(class lab2::Gregorian const &)" (??4Gregorian@lab2@@QAEAAV01@ABV01@@Z) C:\Users...\test.obj Calendar
telling me that it can't find the function
It's telling me that operator=
in the Date
class (obviously because it's purely virtual). Why isn't it using any of the overridden ones?Gregorian::operator=
is trying to call Date::operator=
?
Here's the simplified code where things go wrong:
namespace cal_lib {
template <typename T>
class Calendar {
public:
Calendar() {
today = T(); // this yields the error
}
private:
T today;
};
}
And here's a snippet from Gregorian.cpp:
namespace cal_lib {
class Gregorian : public Date {
public:
Gregorian();
virtual Gregorian& operator=(const Date& date);
virtual Date& add_year(int n = 1);
virtual Date& add_month(int n = 1);
};
// here I'm using Date's constructor to get the current date
Gregorian::Gregorian() {}
Gregorian& Gregorian::operator=(const Date& date) {
if (this != &date) {
// these member variables are specified as
// protected in Date
m_year = 1858;
m_month = 11;
m_day = 17;
add_year(date.mod_julian_day()/365);
add_month((date.mod_julian_day() - mod_julian_day())/31);
operator+=(date.mod_julian_day() - mod_julian_day());
}
}
}
The (default) constructor of Date simply sets the values of m_year
, m_month
and m_day
to today's date:
Date::Date() {
time_t t;
time(&t);
struct tm* now = gmtime(&t);
m_year = now->tm_year + 1900;
m_month = now->tm_mon + 1;
m_day = now->tm_mday;
}
It's worth noting though that this works perfectly fine:
Gregorian g;
Julian j;
g = j; // no problems here
Date* gp = new Gregorian();
Date* jp = new Julian();
*gp = *jp; // no problems here either
This is how the Calendar
class is instantiated:
using namespace cal_lib;
Calendar<Gregorian> cal;
Is there some very obvious mistake here that I'm doing?