It seems that in virtual inheritance, operator= and copy constructor are treated differently. Consider the following code:
#include <iostream>
#include <ostream>
class A {
public:
A(int x) : x(x) {
std::cout << "A is initialized" << std::endl;
}
A(const A& rhs) {
std::cout << "Copy constructor for A" << std::endl;
}
A& operator=(const A& rhs) {
std::cout << "A::operator=()" << std::endl;
return *this;
}
virtual void funcB() = 0;
virtual void funcC() = 0;
int x;
};
class B : virtual public A {
public:
B(int x) {
std::cout << "B is initialized" << std::endl;
}
B(const B& rhs) {
std::cout << "Copy constructor for B" << std::endl;
}
B& operator=(const B& rhs) {
std::cout << "B::operator=()" << std::endl;
return *this;
}
void funcB() override {
std::cout << "B" << std::endl;
}
void funcC() override = 0;
};
class C : public B {
public:
C(int x) : A(x 1), B(x) {
std::cout << "C is initialized" << std::endl;
}
void funcC() override {
std::cout << "C" << std::endl;
}
};
int main() {
C c(1);
C c2(c);
c2 = c;
std::cout << c.x;
}
Here B inherit virtually from A and C inherit from B. The output is:
A is initialized
B is initialized
C is initialized
Copy constructor for A
Copy constructor for B
B::operator=()
2
We can see that the default copy constructor of C has successfully called the copy constructor for both B and A, which is what I want. But the default operator= did not call operator= of A, which is strange.
A possible explanation to this is that the copy constructor of A is called by B, not C. However, since I have deliberately made B pure virtual, I don't have to initialize A in the copy constructor of B and in fact I did not. So the copy constructor of A is called most likely from C, but I have no proof of it since A will be initialized before B anyway, no matter who calls its constructor.
CodePudding user response:
you're using compiler generated operator=
(i.e C::operator=(const C&)
), which calls operator=
for all it's direct base class (and members)
since A
is not a direct base class of C
, A::operator=(const A&)
is not called.
B
is expected to copy A
if it want, unlike constructor, you can implement assignment for B
that doesn't change it's A
(or whatever you want)
on the other hand, if A
is direct base class
class C : public B , virtual public A { ... }
then the compiler generated operator=
would call A
's assignment operator (and it's unspecific whether A
is assigned multiple times)
CodePudding user response:
c2 = c;
Here we call operator= but class C doesn't have it (it is not generating in your case) then we call from base class B which has and it happens because we can cast C to B. That is why you see this message B::operator=().
If we call operator= it doesn't mean that it will call all operator= from base classes. operator= is a method that doesn't have the same behavior as constructors or destructors. If you want to see copy for A class then add next:
B& operator=(const B& rhs) {
A::operator=(rhs);
std::cout << "B::operator=()" << std::endl;
return *this;
}
If you don't explicitly call for A::operator= consequently it doesn't copy - the value x is always be same after initialization.