It is to my understanding that in C++, derived classes do not inherit overloaded assignment operators from base classes. I have written an example below where I explicitly overload the assignment operator for both a base class and a derived class. In the sample output at the bottom, there is a section:
Index:1 - Base Value:1
Index:1 - Derived Value:2
Index:2 - Base Value:2
Index:2 - Derived Value:2
The intended output should have been:
Index:1 - Base Value:2
Index:1 - Derived Value:2
Index:2 - Base Value:2
Index:2 - Derived Value:2
This output was not unexpected. I realize that the assignment operator isn't inherited. Is there a de facto safe/standard approach to having a derived class call the base class's assignment operator? My best guess so far is to have the derived class's assignment operator function up-cast the derived class object to a base class object and assign the RHS to the LHS. Is this a generally-accepted-as-safe approach?
If I use the "Proposed Solution" (bottom of page), it works, but only because none of the operators are declared as virtual
. If I up-cast and use a non-virtual function, the version of the function used depends on the cast, while if I use a virtual function, the member function used depends on the actual type of the object rather than what it is being cast as.
Thank you.
Code Listing
/*******************************************************************************
* Preprocessor Directives
******************************************************************************/
#include <iostream>
using namespace std;
/*******************************************************************************
* Class Declarations and Function Prototypes
******************************************************************************/
class Base {
private:
protected:
public:
int iBInt;
Base(); /* Constructor */
Base(int a); /* Constructor - Set const member */
Base & operator=(const Base& rhs);
virtual ~Base();
};
class Derived : public Base {
private:
protected:
public:
int iDInt;
Derived(); /* Constructor */
Derived(int a); /* Constructor - Set const member */
Derived & operator=(const Derived& rhs);
~Derived();
};
/*******************************************************************************
* Class and Function Definitions
******************************************************************************/
/******************************************************************************/
Base::Base(void) {
cout << __FUNCTION__ << endl;
iBInt = 0;
cout << "iBInt: " << iBInt << endl;
}
/******************************************************************************/
Base::Base(int a) {
cout << __FUNCTION__ << endl;
iBInt = a;
cout << "iBInt: " << iBInt << endl;
}
/******************************************************************************/
Base::~Base(void) {
cout << __FUNCTION__ << endl;
}
/******************************************************************************/
Base& Base::operator=(const Base& rhs) {
cout << "Base::" << __FUNCTION__ << endl;
if (this == &rhs) {
return *this;
}
iBInt = rhs.iBInt;
cout << "iBInt: " << iBInt << endl;
return *this;
}
/******************************************************************************/
Derived::Derived(void) {
cout << __FUNCTION__ << endl;
iDInt = 0;
cout << "iDInt: " << iDInt << endl;
}
/******************************************************************************/
Derived::Derived(int a) : Base(a) {
cout << __FUNCTION__ << endl;
iDInt = a;
cout << "iDInt: " << iDInt << endl;
}
/******************************************************************************/
Derived::~Derived(void) {
cout << __FUNCTION__ << endl;
}
/******************************************************************************/
Derived& Derived::operator=(const Derived& rhs) {
cout << "Derived::" << __FUNCTION__ << endl;
if (this == &rhs) {
return *this;
}
iDInt = rhs.iDInt;
cout << "iDInt: " << iDInt << endl;
return *this;
}
/*******************************************************************************
* Main Entry Point
******************************************************************************/
int main(void) {
int count = 3;
/* Generate objects */
Derived **bArr = new Derived*[count];
for (int i=0; i<count; i++) {
bArr[i] = new Derived(i);
}
/* Set some values via overloaded assignment operator, and print out
* updated values.
*/
for (int i=0; i<count; i++) {
cout << "Index:" << i << " - Base Value:" << bArr[i]->iBInt << endl;
cout << "Index:" << i << " - Derived Value:" << bArr[i]->iDInt << endl;
}
*bArr[1] = *bArr[2];
for (int i=0; i<count; i++) {
cout << "Index:" << i << " - Base Value:" << bArr[i]->iBInt << endl;
cout << "Index:" << i << " - Derived Value:" << bArr[i]->iDInt << endl;
}
/* Cleanup */
for (int i=0; i<count; i++) {
delete bArr[i];
}
delete [] bArr;
return 0;
}
Sample Output
Base
iBInt: 0
Derived
iDInt: 0
Base
iBInt: 1
Derived
iDInt: 1
Base
iBInt: 2
Derived
iDInt: 2
Index:0 - Base Value:0
Index:0 - Derived Value:0
Index:1 - Base Value:1
Index:1 - Derived Value:1
Index:2 - Base Value:2
Index:2 - Derived Value:2
Derived::operator=
iDInt: 2
Index:0 - Base Value:0
Index:0 - Derived Value:0
Index:1 - Base Value:1
Index:1 - Derived Value:2
Index:2 - Base Value:2
Index:2 - Derived Value:2
~Derived
~Base
~Derived
~Base
~Derived
~Base
Proposed Solution/Edit
/******************************************************************************/
Derived& Derived::operator=(const Derived& rhs) {
cout << "Derived::" << __FUNCTION__ << endl;
if (this == &rhs) {
return *this;
}
Base* b1 = this;
Base* b2 = (Base*)&rhs;
*b1 = *b2;
iDInt = rhs.iDInt;
cout << "iDInt: " << iDInt << endl;
return *this;
}