gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > friendship and operator=

#13334 - sajiimori - Thu Dec 11, 2003 7:20 am

Code:

void test();

class Base
{
  protected:
    void f() {}
    void operator+(int) {}
    void operator=(int) {}
};

class Derived : public Base
{
    friend void test();
};

void test()
{
    Derived d;
    d.f();
    d + 5;
    d = 2;    // this line doesn't compile
}

It says there's no match for the `Derived& = int' operator. Why would other protected methods work, but not operator=?

#13338 - MumblyJoe - Thu Dec 11, 2003 7:58 am

Well I wont pretend to understand why you would want to hide an overloaded operator behind a protective shield, but I think your problem is based around the fact that op= is created by the compiler sometimes etc, and I think it may not inherit correctly, much like constructors dont inherit because it wouldnt make much sense for them to do so.

I changed your code to this to verify my theory:
Code:
class Base
{
    public:
    void f() {}
    void operator+(int) {}
    void operator=(int) {}
};

class Derived : public Base
{
};

int main()
{
    Base b;
    b = 2;

    Derived d;
    d.f();
    d + 5;
    d = 2;
}


I get the exact same error as you (using a borland compiler), so it clearly has nothing to do with protected inheritance or friend declarations. I think the simple fact is that you have to do a new op= for each class that derives.
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!

#13357 - sajiimori - Thu Dec 11, 2003 7:33 pm

That's interesting...I agree that the only apparent difference between operator= and other operators is that the compiler sometimes generates a version of operator=. But the only version it should generate is Type& operator=(const Type&) -- not e.g. void operator=(int) -- so I don't see why it shouldn't work.

Anyway, if it doesn't work on GCC or Borland, I guess it's pretty hopeless...

The reason I was hiding some operators is the same reason you would hide any other method -- I want to restrict access at compile-time.

#13389 - Sweex - Fri Dec 12, 2003 12:29 pm

I don't think it's got anything to do with the friend relation. In most cases, the compiler provides an implementation of operator =. If you define your own in a base class the compiler realizes it should not create one but use the one that's defined.

As I see it, you cannot have two implementations of operator = because it cannot work out which one to use in all situations. You have an inherited (protected) operator = from class Base, and the compiler will create a default one for the class Derived.
_________________
If everything fails, read the manual: If even that fails, post on forum!

#13402 - sajiimori - Fri Dec 12, 2003 6:35 pm

Quote:

I don't think it's got anything to do with the friend relation.

MumblyJoe has corrected me on that.
Quote:

In most cases, the compiler provides an implementation of operator =.

It will provide an implementation of C& operator=(const C&) if you don't provide your own, but that's all.
Quote:

As I see it, you cannot have two implementations of operator = because it cannot work out which one to use in all situations.

Of course you can. This code works fine:
Code:

struct C
{
    void operator=(int) { cout << "int"; }
    void operator=(char) { cout << "char"; }
    void operator=(double) { cout << "double"; }
};

void test()
{
    C c;
    c = 5;
    c = 'A';
    c = 1.23;
}

The compiler will give an error if there's an ambiguity, in which case you can be more explicit.

#13535 - Burton Radons - Tue Dec 16, 2003 6:26 am

This is standard (over.oper, paragraph 6). Here's a quote:

C++ draft standard, over.oper, paragraph 6 wrote:
The meaning of the operators =, (unary) &, and , (comma), predefined for each type, can be changed for specific class and enumeration types by defining operator functions that implement these operators. Operator functions are inherited in the same manner as other base class functions, but because an instance of operator= is automatically constructed for each class (_class.copy_, _over.ass_), operator= is never inherited by a class from its bases.

#13540 - Sweex - Tue Dec 16, 2003 11:15 am

Perhaps I should've written a bit more, sajiimori, as you're right that you can have multiple operator =. I meant two implementations of C& operator=(const C&), one in the base clas and one in the derived.

Anyway, what Burton Radons says sounds right to me!
_________________
If everything fails, read the manual: If even that fails, post on forum!

#13562 - sajiimori - Tue Dec 16, 2003 7:35 pm

Thanks!