Quiz 7 — Answers¶
Q1 — B, the dynamic type of the object. For a virtual call through a pointer or
reference, the function is chosen at run time from the type of the object actually there —
not from the declared type of the pointer. That is what lets one loop serve many derived
types.
Q2 — False. override changes nothing at run time. It is a compile-time check: it
tells the compiler "I intend to override a virtual function", so a mismatch (a typo in the
signature, a missing const) becomes a compile error instead of a silently new function.
Q3 — A, B, D. A virtual destructor makes deleting through a base pointer destroy the whole object (A); without it the behaviour is undefined (B); and it enables the derived destructor to run (D). It does not make the class abstract (C) — only a pure virtual function does that.
Q4 —
greet() is not virtual, so ref.greet() uses the static type Base — printing "base".
hello() is virtual, so it uses the object's real type Derived — "derived". d.greet()
knows the type is Derived, so it prints "derived".
Q5 — It prints ..., because the Dog was sliced. std::vector<Animal> stores
Animal values, so push_back(Dog{}) copies only the Animal part; the override is
lost. The fix is to store pointers — std::vector<std::unique_ptr<Animal>>.
Q6 — Base has no virtual destructor, so delete p; (a pointer whose static type is
Base*) has undefined behaviour: in practice only ~Base runs, so anything Derived
owns leaks. Fix:
The rule: a class designed to be deleted through a base pointer needs a virtual destructor.
Q7 — Base::describe runs. During base-class construction the object's dynamic type is
Base — the Derived part does not exist yet — so the virtual call cannot reach the
override. The general rule: a virtual call in a constructor or destructor never dispatches
to a more-derived override.
Q8 — Because a reference or pointer can refer to a derived object while keeping its real type, so the compiler can look up the actual type at run time. A value parameter or container copies the object into a base object, cutting off the derived part (slicing), so there is nothing left to dispatch to.
Q9 — std::vector<std::unique_ptr<Shape>>, where Shape is an abstract base with a
pure virtual area(). The loop uses only the Shape interface:
and never names a concrete shape — the call dispatches to the real type at run time.
Q10 — virtual makes the call resolve at run time to the most-derived override — it
changes behaviour. override is a compile-time promise that this function does override
a virtual one — it changes what the compiler checks, not what the program does. A class can
have virtual without any override, and override without virtual on the same line is
an error.
Marking. One point per question (Q3 all-or-nothing). Then read Marking Yourself.