Assignment operator inheritance
You don't have a default
Derived& operator=(const Base& a);
in your Derived
class.
A default assignment operator, however, is created:
Derived& operator=(const Derived& a);
and this calls the assignment operator from Base
. So it's not a matter of inheriting the assignment operator, but calling it via the default generated operator in your derived class.
Is the assignment operator inherited or not?
The generated assignment is "all the base assignments, in order of inheritance declaration", so your generated assignment is essentially
D& operator=(const D& d)
{
B::operator=(d);
return *this;
}
If you were to derive from both B
and C
- in that order; class D: B, C
- it would be equivalent to
D& operator=(const D& d)
{
B::operator=(d);
C::operator=(d);
return *this;
}
That is, the assignment is not inherited, but it's used.
C++ assignment operator implementation on derived class
Like this:
Derived &operator=(const Derived &right )
{
if (&right == this) { return *this; } // prevent assigning to self
Base::operator=(right);
delete derivedMember; // remember to release any assigned memory (assumes derivedMember is assigned a default of nullPtr)
derivedMember = new double( *(right.derivedMember) );
return *this;
}
Calling copy and assignment operators from base class to create inherited class instances in C++
Yes, you would have to define something like that.
B(const A& other);
This would allow constructing B
out of A
. This would also allow assigning A
to B
by way of implicitly converting A
to B
and then assigning. So that alone should suffice. But you get an extra copy.
B& operator=(const A& other);
This makes assigning A
to B
more efficient since you avoid the extra copy of the temporary B
. This should also allow assigning things that can be implicitly converted to A
like:
B b = 1;
If you don't want that you might have to add some explicit
. Did C++98 have explicit? That is so last millenium.
Note: In modern C++ this would be more efficient because of copy elision and because you could use move semantic and perfect forwarding references.
Assignment operator not available in derived class
Every class has at least one assignment operator implicitly defined when we don't provide one ourselves.
And when a member function in a derived class is defined with the same name as a member in the base class, it hides all the base class definitions for that name.
You can use a using declaration, but be warned that it will pull all the members named operator=
and allow code like this:
A a;
B b;
b = a;
Which is slightly dubious.
Move assignment operator and virtual inheritance
The problem is that FT
's FT& operator= (FT&&) = default;
is essentially:
FT& operator=(FT&& other) {
// Move-assign base classes
static_cast<UG&>(*this) = std::move(static_cast<UG&>(other)); // Also move-assigns G
// other.mem_G is now empty after being moved
static_cast<T&>(*this) = std::move(static_cast<T&>(other)); // Also move-assigns G
// this->mem_G is now empty
// Move-assign members
mem_FT = std::move(other.mem_FT);
}
(Though not exactly. A compiler is allowed to be smart and only move from a virtual base class once, but that doesn't happen with gcc and clang at least)
Where the single base class subobject G
is moved into from other
twice (through the two move assigns). But other.mem_G
is empty after the first move, so it will be empty after the move assign.
The way to deal with this is to make sure that the virtual base is only move-assigned once. This can easily be done by writing something like this:
FT& operator=(FT&& other) noexcept {
// Also move-assigns `G`
static_cast<T&>(*this) = std::move(static_cast<T&>(other));
// Move-assign UG members without UG's move assign that moves `G`
mem_UG = std::move(other.mem_UG);
// Move-assign FT members
mem_FT = std::move(other.mem_FT);
}
With private members or a more complicated move-assign, you might want to make a protected move_only_my_members_from_this_type_and_not_virtual_bases(UG&&)
member function
You can also fix this by not generating a default move-assign operator, making the base class be copied twice instead of becoming empty, for a potential performance hit.
Related Topics
Dynamically Allocated Memory After Program Termination
Prefix/Postfix Increment Operators
How to Access Private Data Members Outside the Class Without Making "Friend"S
How to Automatically Register a Class on Creation
Std::Unique_Ptr for C Functions That Need Free
When Is a Function Try Block Useful
Class Template Argument Deduction Not Working with Alias Template
Understanding Double Dispatch C++
When Is It Worthwhile to Use Bit Fields
On Local and Global Static Variables in C++
What Does It Mean for a C++ Function to Be Inline
What's a Good Hash Function for English Words
How to Change the Background Color of a Button Winapi C++
Can the "Application Error" Dialog Box Be Disabled
How to Tell If the C Function Atoi Failed or If It Was a String of Zeros
Template Specialization of a Single Method from a Templated Class