Polymorphic Big Five
You need to be very careful with Polymorphic Big Five, because there are a few problems that can occur. Learned these in CS247.
Consider the following example:
- Title, author and length are set, but topic remains unchanged.
Problem 1: Partial Assignment (because of non-virtual
)
Book::operator=
is defined as non-virtual. We’re calling operator=
method on a reference. We use the static type, call Book::operator=
, even though br1
and br2
are referencing texts.
Some fields are copied, but not all. This is the partial assignment problem.
How to fix this? Declare Book::operator=
as virtual!
In Text
, we can’t just have the following:
- Not a valid Function Override (arguments are different)
Signature must be the following
However, trying to fix this partial assignment this way introduces 2 new problems:
- We can’t access
other
’s topic, because it’s aBook
, andBook
don’t have topics, onlyTexts
do. - other is a
Book&
, so now, we get the mixed assignment problem…
Problem 2: Mixed Assignment Problem (because of virtual
)
Now, the following is legal:
We can see that we can set a Text
to a Comic
, as the Comic
on right-hand side can be implicitly converted to a const Book&
.
Setting operator=
to virtual creates the is the mixed assignment problem, as we can now can set subclass siblings to each other.
In summary
- Non-virtual operator = leads to partial assignment
- virtual operator = mixed assignment
To fix this, we need to restructure the Book
hierarchy:
- notice that
operator=
is under protected now
To make this abstract, we need a Pure Virtual Method. If no other methods make sense to be pure virtual, can always use destructor.
How does this fix the two problems?
- Mixed assignment:
operator=
is non-virtual and the implicitly provided copy assignment operator only acceptsText
. - Partial assignment problem:
Only works since
AbstractBook
is an abstract classI am still confused on why the teacher says “only works because it’s abstract class”.
I guess only works is maybe the wrong word. Because we are setting
AbstractBook::operator=
to protected. we are ensuring that we can’t assign books to one another. IfBook
was a concrete class, this would be kind of bad, because we DO want to be able to assign books to one another.
TODO BRAINF-CK IDK WHAT’S GOING ON?? Okay, I am getting brainf-cked, wha
- Is it because of how I saw assignment operator doesn’t get inherited?
- From my understanding,
Text
is callingoperator=(const Abstract& other)
, which it has access to because of inheritance. But even making the function public does not fix the problem. “no operator ”=” matches these operands”
Also see Method Safety Levels, weird stuff going on for what it means to be able to “access” something.
Other small problem: Destructor
Consider Text
’s destructor. Implicitly, following happens:
- Destructor body runs (empty)
- Object fields we destructed in reverse decl. order
- Superclass destructor runs
- Space is reclaimed
Because in step 3, Text
’s destructor calls AbstractBook’s destructor, we have a problem: we’ve called a method with no implementation.
Solution: give it an implementation: