The purpose of this quiz is to give you a chance to focus your knowledge of [run-time] polymorphism in C++.
The idea behind polymorphism is to allow a ____ pointer to point to objects from any ____ class. In this way, the ____ can 'remember' which actual ____ it was pointing to and call the correct ____ method.
TRUE ✓ | FALSE ✗ | In polymorphism, the keyword virtual is used. | ||
---|---|---|---|---|
TRUE ✓ | FALSE ✗ | Once a method (of a particular overload signature) is virtual, any derived classes which override it are using polymorphism. | ||
TRUE ✗ | FALSE ✓ | Of course, the derived classes must still use the virtual keyword for this to work. | ||
TRUE ✗ | FALSE ✓ | Overloaded methods of this signature will also be polymorphic. |
Given a non-polymorphic hierarchy such as:
class One { public: void print(void); }; class Two : public One { public: void print(void); };
Tell what happens in the following code:
One o; Two t; One * p; p = &o; p->print(); p = &t; p->print();
The first call to print is for One::print and the second call to print is also One::print.
Why is this happening?
The hierarchy is non-polymorphic. The One::print function is not marked virtual.
Re-evaluate the above code but add the word virtual to the print method(s). Show the new classes, too.
class One { public: virtual void print(void); }; class Two : public One { public: virtual void print(void) override; }; This time, the first print call is still to One::print, but the second call is to Two::print. This is because of the introduction of polymorphism into the hierarchy. Only the One::print needed the virtual keyword. The Two::print didn't need either virturl or override for this to work, but they make intent more clear to all programmers on the project.
How can you use polymorphism to store different (but related) objects in the same container (array/vector)? Show (pseudo)code to do this. (Hint: Maybe you could use the Shape hierarchy we discussed in lecture?) (Yes, you'll have to show the necessary parts of the polymorphic hierarchy AND the code to use the container.)
class Shape { public: virtual void print(ostream & os) const; }; class Circle : public Shape { public: virtual void print(ostream & os) const override; }; class Cube : public Shape { public: virtual void print(ostream & os) const override; }; { constexpr size_t MAX = 5; Shape * container[MAX]; container[0] = new Circle; container[0] = new Circle; container[0] = new Cube; container[0] = new Circle; container[0] = new Cube; for (size_t i = 0; i < MAX; ++i) { container[i]->print(cout); } for (size_t i = 0; i < MAX; ++i) { delete container[i]; container[i] = nullptr; } }
TRUE ✓ | FALSE ✗ | Of all the methods to make virtual, the most important is the destructor. | ||
---|---|---|---|---|
TRUE ✓ | FALSE ✗ | If the destructor isn't virtual, derived class objects deleted via a base pointer won't be completely destroyed and we will fragment our heap. |