2

The cppreference says:

Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.

From my understanding, the following code should not compile. Because

  1. B::operator=(const B&) is implicitly declared.
  2. both A::operator=(const A&) and using-declaration are hidden.
#include <iostream>
using namespace std;

class A { 
 public:
    A& operator=(const A& A) {
        cout << "A::opreator=" << endl;
    }   
};

class B : A { 
 public:
    using A::operator=;
};

int main() {
    A a1; 
    B b1; 
    b1 = a1; 
}

However, it compiles successfully and prints "A::operator=", why?

Heyi Sun
  • 23
  • 3
  • 1
    your second reason, you say that both operators are hidden, but you have them public. what do you mean by hidden? – Henri Jun 23 '20 at 01:15
  • 1
    The `using` declaration says that `B::operator=` is the same as `A::operator=`. – bitmask Jun 23 '20 at 02:49
  • @bitmask I don't think that is really the way to think of it. Should there be a data variable added to class `B` then the compiler will create an assignment operator if needed for class `B` which will use the `A::operator=()` of class `A` for the class `A` part of the assignment. The `using` allows for those necessary parts of class `A`, `operator=()` in this case, to be exposed and available to class `B` objects because otherwise `A` is private and hence not exposed to `B` since `public` inheritance is not specified or being used. – Richard Chambers Jun 23 '20 at 03:44
  • @Henri Yeah, that's what I am asking. The standard says they are hidden and from my understanding, the standard means that both using statement and A::operator=() are not effective because of the implicitly declared B::operator=() 'hide' them. Maybe my understanding is wrong, but I still want to know what the meaning of 'hidden' is here? – Heyi Sun Jun 23 '20 at 21:16

4 Answers4

1

You can't hide the copy assignment operator of B because both operators you've mentioned take different parameters.

asmmo
  • 6,922
  • 1
  • 11
  • 25
1

From C++11 Standards#12.8 [emphasis added]:

24 Because a copy/move assignment operator is implicitly declared for a class if not declared by the user, a base class copy/move assignment operator is always hidden by the corresponding assignment operator of a derived class (13.5.3). A using-declaration(7.3.3) that brings in from a base class an assignment operator with a parameter type that could be that of a copy/move assignment operator for the derived class is not considered an explicit declaration of such an operator and does not suppress the implicit declaration of the derived class operator; the operator introduced by the using-declaration is hidden by the implicitly-declared operator in the derived class.

The implicit declaration of class B assignment operation will be like this:

B& B::operator=(const B&)

The parameter type of using-declaration assignment operator in class B is different from implicitly declared assignment operator. Hence, it suppress the implicit declaration of the derived class B operator.

For understanding on 1 & 2 w.r.t. to the code you have posted:

  1. No, the implicit declaration of assignment operator is suppressed in class B.
  2. No, they will not be hidden.
H.S.
  • 11,654
  • 2
  • 15
  • 32
  • Experiments with MSVC 2017 indicates that if I add a variable to the class `B` and with two class `B` variables, `b1` and `b2`, when I do an assignment, `b2 = b1;` an implicit assignment for class `B` is created which uses the class `A` version of `operator=`. The class `B` variable value changes and I see print indicating `A::operator=` was called. I see it in the debugger as well. Using modified class `B` when `b1=a1;` I see the `A::operator=` executed. If I then add `B::operator=(A &a)` then `b1 = a1:` uses that yet `b2 = b1;` uses `A:operator=` instead. – Richard Chambers Jun 23 '20 at 12:10
  • Thank you for your explanation. Could you please provide an example that the using statement and A::operator=() are hidden by the implicitly declared B::operator=() ? – Heyi Sun Jun 23 '20 at 21:46
  • I changed `A::operator=()` to `void A::operator=(const B& b) { cout << "A::opreator=(B)" << endl;}`. But this does not compile: `int main() { B b1, b2; b1 = b2; }` Why? I think B::operator=() hides using and A::operator() and `b1 = b2` should invokes B::operator() without compile error. – Heyi Sun Jun 23 '20 at 21:52
  • @HeyiSun _But this does not compile:_ what is the error you are getting? – H.S. Jun 24 '20 at 01:06
  • @RichardChambers If you have `using A::operator=;` in class `B`, the implicit declaration of assignment operator will not be provided by compiler. Both `b3=b1;` and `b1=a1;` will call `A::operator=`. If you add `B::operator=(A &a)`, now base class `operator=` is hidden. `b1=a1` will call `B::operator=(A &a)` but `b2=b1` will call `B& B::operator=(const B&)` which is synthesized by compiler and it calls the base class `operator=`. Try adding `B& B::operator=(const B&)` in class explicitly and check the behavior. – H.S. Jun 24 '20 at 02:37
0

I think the reference you mentioned should be broken into 2 parts that suite your 2 question:

  1. Yes, the copy assignments for base class (A) and derived class(B) are implicitly declared by default. You just overriden the implicit declaration on class A by output a message to stream.
  2. the second part of the reference means that if the instance of class B is assigned to an instance of class A and there is a using-declaration to use class A assignment, then the assignment of class A will be used. Which means, if an instance of class B is assigned to an other instance of class B, the default implicit assignment will be used. Therefore, nothing is hidden due to the difference in argument type and the code will call the using-declaration (a.k.a the base class assignment) => the message is output to stream.
Thế Long
  • 516
  • 7
  • 19
0

I don't see any conflict in this code with standard. b1 = a1; This assignment is done because you used using-declaration of base class. and also " implicit assignment operator of the derived class" is provided by compiler because if you want to assign two objects of derived class it's possible.

Farhad Sarvari
  • 1,051
  • 7
  • 13