I am trying to call the assignment operator from the base class (shape) in the derived class (point). I get an unresolved external linker error and I don't understand why. I put "virtual" in front of the base assignment operator and placed the base assignment operator inside of my derived class at the end. Where did I go wrong?
#ifndef SHAPE_H
#define SHAPE_H
#include <iostream>
using namespace std;
namespace Joe
{
namespace CAD
{
class Shape
{
private:
int m_id;
public:
Shape(); //default constructor
~Shape(); //destructor
Shape(const Shape& s); //copy constructor
virtual Shape& operator = (const Shape& source); //assignment operator
string ToString() const; //returns id as a string
friend ostream& operator << (ostream& os, const Shape& sh); //global function that can access private members
int ID() const;
};
inline int Shape::ID() const //retrieve ID of shape
{
return m_id;
}
}
}
#endif
#ifndef POINT_H
#define POINT_H
#include <iostream>
#include "shape.h"
namespace Joe
{
namespace CAD
{
class Point: public Shape
{
private:
double m_x;
double m_y;
public:
Point(); //default constructor
~Point(); //destructor
Point(const Point& pt); //copy constructor
Point(double newX, double newY) //constructor accepting x and y coordinates
{
m_x = newX;
m_y = newY;
std::cout << "Point(" << m_x <<","<< m_y <<")" << std::endl;
}
Point(double val); //constructor accepting one double
void X(double newXval) {m_x = newXval;} //default inline setter
void Y(double newYval) {m_y = newYval;} //default inline setter
double X() const; //getter pre-inline
double Y() const; //getter pre-inline
std::string ToString() const; //returns a string description
//distance functions
double Distance() const; //calculate the distance to the origin (0,0)
double Distance(const Point& p) const; //calculate the distance between two points
//operator overloading
Point operator - () const; //negate the coordinates
Point operator * (double factor) const; //scale the coordinates
Point operator + (const Point& p) const; //add coordinates
bool operator == (const Point& p) const; //equally compare operator
Point& operator = (const Point& source); //assignment operator
Point& operator *= (double factor); //scale the coordinates and assign
friend std::ostream& operator << (std::ostream& os, const Point& p); //send to ostream (friend)
Shape& operator = (const Shape& source); // call assignment operator of base class
};
inline double Point::X() const //normal inline getter
{
return m_x;
}
inline double Point::Y() const //normal inline getter
{
return m_y;
}
}
}
#endif
Shape& Shape::operator = (const Shape& source) //assignment operator
{
if (this == &source) //avoid self-assignment
return *this;
cout << "shape assignment" << endl;
m_id = source.m_id;
return *this;
}
Point& Point::operator = (const Point& source) //assign
{
if (this == &source) //avoid self-assignment
return *this;
m_x = source.m_x;
m_y = source.m_y;
return *this;
}
Your problem might be that you define the class in a namespace, but you define the operators outside that namespace without specifying it. Because of this, the compiler can't connect the definition to the declaration.
Ishamael pointed out that you don't specify what happens when a non-Point Shape is assigned to a Point. This is necessary for a virtual assignment operator; see his answer. But this virtual assignment operator could end up doing a lot of unexpected things, like cutting off parts of objects if the wrong types are assigned to each other.
You don't need the virtualness to ensure that the Shape operator also gets called when Point is assigned. Just call the Shape operator inside the Point operator. Making the operator virtual would actually have the opposite effect; the Point operator would override the Shape operator even if the instance you're calling it with is referred to as a Shape.
Point& Point::operator = (const Point& source) //assign
{
if (this == &source) //avoid self-assignment
return *this;
Shape::operator=(source); // also call the base class operator
m_x = source.m_x;
m_y = source.m_y;
return *this;
}