Quiz 7 — Polymorphism¶
Ten questions on run-time dispatch — and on the ways polymorphic code goes wrong: slicing, a missing virtual destructor, and dispatch during construction.
Attempt all of them closed-book, then mark yourself against the answers.
Concepts: virtual · dynamic dispatch · override · virtual destructor · object
slicing · dispatch in constructors.
Q1. (MCQ) What decides which function runs for a called virtual member function?
- A. the static type of the pointer or reference
- B. the dynamic type of the object at run time
- C. the compiler's choice at link time
- D. the order the functions are declared in
Q2. (true/false) Marking a derived function override changes what the program
does at run time.
Q3. (multiple-select) Why should a polymorphic base usually have a virtual destructor? Select all that apply.
- A. So deleting through a base pointer destroys the whole object
- B. Because otherwise the behaviour is undefined
- C. To make the class abstract
- D. To allow the destructor to be overridden
Q4. (predict) Write the three output lines.
#include <iostream>
class Base {
public:
void greet() const { std::cout << "base\n"; }
virtual void hello() const { std::cout << "base\n"; }
virtual ~Base() = default;
};
class Derived : public Base {
public:
void greet() const { std::cout << "derived\n"; }
void hello() const override { std::cout << "derived\n"; }
};
int main() {
Derived d;
const Base& ref = d;
ref.greet();
ref.hello();
d.greet();
}
Q5. (predict) What does this print, and why is it not woof?
#include <iostream>
#include <string>
#include <vector>
class Animal {
public:
virtual std::string speak() const { return "..."; }
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
std::string speak() const override { return "woof"; }
};
int main() {
std::vector<Animal> zoo;
zoo.push_back(Dog{});
std::cout << zoo[0].speak() << '\n';
}
Q6. (debug) This deletes a derived object through a base pointer. State what is wrong and fix it.
class Base {
public:
~Base() { }
};
class Derived : public Base {
public:
~Derived() { }
};
int main() {
Base* p = new Derived;
delete p;
}
Q7. (analysis) A Base constructor calls a virtual describe(), which Derived
overrides. Which version runs, and what is the general rule?
Q8. (short answer) Why must a polymorphic call go through a reference or a pointer rather than a value?
Q9. (design) A drawing tool stores shapes in one container and prints each one's area. State the container type you would use, what the element type is, and how the loop avoids knowing the concrete shapes.
Q10. (analysis) In one sentence each, say what override buys you and what virtual
buys you. They are not the same thing.
Scoring: mark yourself with the answers, then read the self-assessment guide.