Assigning members of base and derived class in operator=

Started by
4 comments, last by Zahlman 17 years, 4 months ago
Is it possible to assign both the members of a base class and the members of a derived class (for a single class A that inherits from B), during a single function call, most likely to the overloaded assignment operator, without explicitly adding the assignment of the individual members? Here's what I came up with, but it does feel a little unwieldy:

class A
{
public:

	int a;

	A& operator=(const A& aobj)
	{
		if( this != &aobj ){
			printf(__FUNCTION__ "\n");

			a = aobj.a;
		}

		return *this;
	}

};



class B	:	public A
{
public:

	int b;

	B& operator=(const B& bobj)
	{
		((A&)(*this)) = A::operator=(bobj);

		if( this != &bobj ){
			printf(__FUNCTION__ "\n");

			b = bobj.b;
		}

		return *this;
	}

};



int main()
{

	B b;
	b.a = 5;
	b.b = 6;

	B d;
	d.a = 7;
	d.b = 8;

	printf("\n\nBefore assignment: b(%d,%d), d(%d,%d)\n\n", b.a, b.b, d.a, d.b);

	b = d;

	printf("\n\nAfter assignment: b(%d,%d), d(%d,%d)\n\n", b.a, b.b, d.a, d.b);

return 0;
}

It doesn't feel right, mostly because you're explicitly calling the A overloaded operator. Am I forgetting if there's already a way to do this?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Advertisement
After short looking at your code, at least this line contains unnecessary code:

((A&)(*this)) = A::operator=(bobj);

You are calling a member function of your base class (since operators are also simple functions and just syntactic sugar).

At the end of your base class function your return a reference to yourself. In that line above you take the reference to yourself get the address of yourself and assign the address of yourself to the this pointer (which allready contains the address of yourself).

So this should be fine anyway:
A::operator=(bobj);

And I would say that you should never assign anything to this itself unless you really know what you are doing (but i guess even then you don't need to mess around with the this pointer).


Btw, in your case even the automatically generated copy constructor and assignment operator will do the job, since you are not doing anything but a binary copy of your objects.
Quote:Original post by Fionn
((A&)(*this)) = A::operator=(bobj);

Yeah, that was kind of stupid. I guess I wasn't paying proper attention to the little details and I was just trying to find a solution.

Quote:Original post by Fionn
Btw, in your case even the automatically generated copy constructor and assignment operator will do the job, since you are not doing anything but a binary copy of your objects.


Anyway, I suppose I didn't explain properly. The auto generated assignment operator would normally be fine, except for the fact that I need to not assign a particular member. This member has to stay the same as when the object was constructed, for it's whole life. This is why I need to explicitly put in an overloaded assignment operator.

Although it's quite possible that something like that is too counter-intuitive.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Quote:Original post by Endar
The auto generated assignment operator would normally be fine, except for the fact that I need to not assign a particular member. This member has to stay the same as when the object was constructed, for it's whole life. This is why I need to explicitly put in an overloaded assignment operator.


Might I suggest that you follow the recommended idiom of implementing your assignment operator in terms of your copy contstructor and a swap() throw() member function. Not only will you eliminate code duplication, but you will gain the benefit of the strong exception guarantee.
  class Base  {  protected:   void swap(const Base& rhs) throw()   { ... }  };  class Derived: public Base  {    Derived(const Derived& rhs)    : m_someMember(rhs.someMember)    , m_uniqueId(s_nextUniqueId++)  // constructs a new object with unique ID    { ... }    Derived& operator=(const Derived& rhs)    {      Derived tmp(rhs);             // does the right thing, may throw      swap(tmp);                    // does not swap unique IDs    }  protected:    void swap(const Derived& rhs) throw()    {      Base::swap(rhs);      std::swap(m_someMember, rhs.m_someMember);    }  private:    int        m_someMember;   ///< gets copied    int        m_uniqueId;     ///< never gets copied    static int s_nextUniqueId;  };


--smw

Stephen M. Webb
Professional Free Software Developer

Also, you should avoid giving base classes copy construcotrs and assignment operators - it will lead to object slicing.
Bregma: You're missing a "return *this;" from the assignment operator. :)

Thanks for reminding me about the whole idea of swap member functions, though. I was going to suggest copy-and-swap but had a brainfart and forgot that this can be used to address "unique ID" situations :)

This topic is closed to new replies.

Advertisement