I am having a strange issue with overloading the assignment operator in an inherited class. My code has the following relevant pieces
class BaseSignal
{
...
virtual void Get(double* val) const {};
virtual void Set(double val) {};
BaseSignal& operator=(const BaseSignal& other);
BaseSignal(const BaseSignal& orig);
...
}
BaseSignal& BaseSignal::operator=(const BaseSignal& other)
{
double dval;
other.Get(&dval);
this->Set(dval);
}
template <class T>
class Net : public BaseSignal
{
...
using BaseSignal::operator=;
T* pval_;
...
void Set(T val)
{
*pval_ = val;
}
}
I don't think that the fact that the derived class is a template matters here.
The problem I'm having is when I evaluate the final equality in the sequence below:
Net<double>* net_real = new Net<double>(...);
*net_real = 1.0;
Net<double>* net_real2 = new Net<double>(...);
*net_real2 = 3.0;
*net_real = *net_real2;
Stepping through the code, all the virtual functions are followed, and indeed the value pointed to by pval_
of net_real
gets updated to 3.0
when the Net<double>::Set
method is called by the overloaded =
operator. The problem is that when I return from the call stack to the next line after *net_real = *net_real2;
, it looks like somehow a shallow copy of net_real2
was performed. Specifically, the pointer pval_
in net_real
now suddenly has the same address as the pointer in net_real2
.
Is somehow the overloaded base =
operator called, THEN the implicit =
operator of the derived class being called? I have not defined any equality/copy constructor of the derived class (but there is an explicitly-defined copy constructor of the base class).
EDIT
I've pasted a block of code below that shows what's going on. I stripped a lot of stuff out, but I hope this shows the problem. I just ran this in [cpp.sh].
// Example program
#include <iostream>
#include <string>
class BaseSignal
{
public:
/**
* Constructor and destructor methods
*/
// Nullor
BaseSignal() {};
// Destructor
virtual ~BaseSignal() {};
// Copy
BaseSignal(const BaseSignal& orig);
// Virtual settors
virtual void Set(double val) {};
// Virtual gettors
virtual void Get(double* val) const {};
// Equality to another signal
BaseSignal& operator=(const BaseSignal& other);
BaseSignal& operator=(const double& rhs);
}; // class BaseSignal
BaseSignal& BaseSignal::operator=(const double& rhs)
{
this->Set(rhs);
return *this;
}
// Equality to another signal. Check vector widths are equal
BaseSignal& BaseSignal::operator=(const BaseSignal& other)
{
std::cout << "******BaseSignal::operator= was called!******\n";
double dval;
other.Get(&dval);
this->Set(dval);
return *this;
}
template <class T>
class Net : public BaseSignal
{
public:
T* pval_;
/**
* Constructors/destructors
*/
Net() : BaseSignal()
{
// Initialize value
pval_ = new T[1]{0};
}
~Net() {delete[] pval_;}
/**
* Operator Overloads
*/
using BaseSignal::operator=;
/**
* Setting with a constant value input just writes to the value at pval_.
* If the Net is a 2-D vector, this method writes all values in the vector
* to be the same val.
*/
void Set(T val)
{
pval_[0] = val;
} // Net<T>::Set
/**
* The Get method returns the number of elements based on the col_
* parameter.
*/
void Get(T* val) const
{
val[0] = pval_[0];
} // Net<T>::Get
};
int main()
{
double read_val;
Net<double>* net_real = new Net<double>();
*net_real = 1.0;
net_real->Get(&read_val);
std::cout << "net_real is equal to: " << read_val << "\n";
std::cout << "net_real has pval_ pointer: " << net_real->pval_ << "\n";
Net<double>* net_real2 = new Net<double>();
*net_real2 = 2.0;
net_real2->Get(&read_val);
std::cout << "net_real2 is equal to: " << read_val << "\n";
std::cout << "net_real2 has pval_ pointer: " << net_real2->pval_ << "\n";
std::cout << "Now assigning value of net_real2 to net_real\n";
*net_real = *net_real2;
net_real->Get(&read_val);
std::cout << "net_real is now equal to: " << read_val << "\n";
std::cout << "net_real now has pval_ pointer: " << net_real->pval_ << "\n";
}