Why cant we overload assignment operator using a friend function?
Please help??
Thanks,
comwizz.

Recommended Answers

All 6 Replies

Why cant we overload assignment operator using a friend function?

operator= can only be a member function. It is intimately connected to the object on the left side of the = .

If it was possible to define operator= globally, then you might attempt to redefine the built-in = sign

int operator=(int, userdefinedtype);

This is the reason due to which you are forced to use operator= as member function.

It is intimately connected to the object on the left side of the =

I dont understand this clearly.

If it was possible to define operator= globally, then you might attempt to redefine the built-in = sign

int operator=(int, userdefinedtype);

I cannot understand this fully , how would globally defining = operator make a difference??
Thanks for your help,
comwizz

>operator= can only be a member function.
Correct.

>It is intimately connected to the object on the left side of the =.
Yes, but not so intimately (ie. constructor or destructor) that a non-member function is completely illogical. You could, if C++ allowed it, do this, and nobody would question how reasonable it is:

class C {
  friend void operator= ( C& lhs, const C& rhs );
};

void operator= ( C& lhs, const C& rhs )
{
  // Assign rhs to lhs
}

>If it was possible to define operator= globally, then you might attempt to redefine the built-in = sign
That's a different issue entirely. It's trivial for an implementation to allow a non-member operator= but disallow defining it on built-in types. The reason operator= is required to be a member is because operator= has default behavior. If you redefine it globally, there's a distinct threat of a = b meaning different things to different parts of the code. Consider this:

struct C {
  // Default operator= (shallow copy)
  char *p;
};

void foo ( C& c )
{
  C scratch;

  // Work with scratch

  c = scratch;
}

void operator= ( C& lhs, const C& rhs )
{
  // Assign rhs to lhs (deep copy)
}

void bar ( C& c )
{
  C scratch;

  // Work with scratch

  c = scratch;
}

int main()
{
  C test;

  foo ( test );
  bar ( test );
}

foo doesn't know that operator= was redefined because function declarations are positional. If you declare an overload after you use the function, the overload isn't recognized. So foo will use the default operator=, which performs a shallow copy and ends up aliasing the pointer in c with the transient pointer in scratch that will get destroyed when foo returns. Therefore you have a memory leak, data loss, *and* an unexpected pointer to freed memory, whereas bar has none of these problems because it uses the overloaded operator= and correctly performs a deep copy.

foo doesn't know that operator= was redefined because function declarations are positional. If you declare an overload after you use the function, the overload isn't recognized. So foo will use the default operator=, which performs a shallow copy and ends up aliasing the pointer in c with the transient pointer in scratch that will get destroyed when foo returns. Therefore you have a memory leak, data loss, *and* an unexpected pointer to freed memory, whereas bar has none of these problems because it uses the overloaded operator= and correctly performs a deep copy.

According to your code the assignment operator could be used as a friend function to class c and the bar function would work correctly as deep copy is implemented . So why not use the assignment operator overloading as a friend function by declaring and defining it above other functions and hence default = operator performing shallow copy would not be called??
Thanks for your help,
comwizz

>So why not use the assignment operator overloading as a friend function
>by declaring and defining it above other functions
Indeed, why not? Just make sure that you get it right for any possible combination of functions and declarations in any number and combination of source files. And also keep a sticky note on your monitor to remind you of such a subtle problem that not even lint can warn you about. Also, don't forget that you need to watch for it in other people's code and any code you maintain, for a seemingly innocent change could introduce serious and difficult to find bugs.

The point is that it's very difficult to error check this problem in any non-trivial project. It's also so subtle that even programmers who are aware of it will be hard pressed to avoid it, much less the more numerous programmers who wouldn't even know the problem exists until it bites them in the ass. Compare that to the current state of affairs where a simple rule avoids the problem entirely, and the simple rule can't be missed because it gives you a compile time error if you don't follow it.

A guiding rule in the design of C++ is that a compile time error is much more desirable than a runtime error.

Thanks Narue.

Your posts are always eye openers.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.