Virtual destination operator

Given the code below, shouldn't be typing Calling B

, should n't Calling A

? Isn't it a runtime type of a

a B

, and hence a virtual call should result in a call B::operator=

(since virtual calls are defined by the left-hand operand)?

#include <iostream>

class A
{
public:
  virtual A& operator=(const A& a_) { std::cout << "Calling A" << std::endl; }
};

class B : public A
{
public:
  virtual B& operator=(const B& b_) { std::cout << "Calling B" << std::endl; }
};

int main() {
  B b1;
  B b2;
  A& a = b1;
  a = b2; // Prints "Calling A", should be "Calling B"?

  return 0;
}

      

+3


source to share


6 answers


a = b2;

- not a virtual call.

The reason for this is that it B::operator=(const B&)

doesn't override A::operator=(const A&)

because their signatures are different.

You can use override

to have the compiler automatically check these things for you.



Usage override

does two things:

  • prevents such simple errors (the compiler is your best friend)
  • makes the code easier to understand ("oh, so this function overrides something")
+3


source


The virtual method you have in B (B::operator=(const B&))

does not override the value in (A::operator=(const A&))

. I assume that you wrote an overload, so the compiler cannot know that such a method exists since you are using reference A.



+2


source


This method:

virtual B& operator=(const B& b_)

      

does not override this method:

virtual A& operator=(const A& a_)

      

To override a base class method, the child must have the same method signature.

The invocation A::operator=

does not postpone implementation to the derived class, because the derived class has no implementation virtual A& operator=(const A& a_)

.

+2


source


a

is an object class A

, the a = b2

reasons will cause A& operator=(const A& a_)

where the type b2

will be converted to type a

. Testing b1 = b2

will output "Call B".

operator=

the override is unique to each class. It makes no sense to declare it as a virtual function.

0


source


First, as everyone said, your override is not - it's just an overload. Use the override keyword to confirm this.

The solution is to give the derived class operator exactly the same signature as the base class, taking A and dynamic_cast to B in the body.

You will need to think about what to do if the caller tries to assign A to B (i.e. the listing does not work). As Alf mentioned in a comment, it is for this reason that virtual assignment is not very popular.

0


source


It will only call A :: operator = .. This is a script overloading method that you cannot achieve in two different classes (even inheriting) due to the name hiding feature in C ++.

-1


source







All Articles