Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Home » Tip Bank » C++
Language: C++
Expertise: Beginner
May 2, 1997

Inherited operator = not being seen

Question:
I have a templated class A that defines two operator =, and a templated class B : public class A which should inherit the two virtual a::operator = I define, but when I instantiate an object B b, it won't see the operator = .

Answer:
You are not going to like this, but the operator = is a special member function that is not inherited, in order to prevent slicing of objects.

Consider:

struct Base
{
	const Base& operator=(const Base& b) {i = b.i;};
private:
	int i;
};

struct Derived : public Base
{
private:
	int i;
};
If the assignment were to be inherited, I could then say: Derived d1,d2; d1 = d2; and only the Base subobject of d1 would get copied, not the Derived part.

To solve this problem, the compiler generates an assignment operator for classes that don't define them (when it can — but that's another story); the rules for that is member-wise, copy starting with the base classes. So, the compiler-generated assignment operator would look something like this:

inline Derived& Derived::operator(const Derived& d)
{
	Base::operator=(d);
	i = d.i;
	return *this;
}
Note that the generated copy assignment operator is inline.

This interesting property of assignment operators also makes it impossible for the assignment to be virtual, because it's not even visible to the clients of the derived class.

So that was the gist of your problem; now, let's try to work out a solution.

Let's rewrite our example classes now and define operator = for the derived class, too.

struct Base
{
	const Base& operator=(const Base& b) {assign(b);return *this;};
protected:
	void assign (const Base& b) { i = b.i;}
private:
	int i;
};

struct Derived : public Base
{
	const Derived&  operator = (const Derived& d) {assign(d);return *this;};
protected:
	void assign(const Base& b) 
	{
		// call base classes assign
		Base::assign(b);

		try
		{
			const Derived &d = dynamic_cast(b);
			i = d.i;
		}
		catch (const bad_cast&)
		{
			// do appropriate error handling
		}
	}
private:
	int i;
};
So now if we have
Derived d1,d2;
and we say
d1 = d2; // this will call Derived::operator =() which calls assign and 
// propagates all the way to the base class and then copies itself.
This has the added advantage of making the assignment operator in the base class behave polymorphically. For example, if we had
Base * b1 = new Derived;
Base * b2 = new Derived;
*b1 = *b2; // would still get the entire object assigned, as opposed to just
the base class subobject.
DevX Pro
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date