Knowledge Test Score Board
— · 0%
Work through the questions below — your score updates as you go.
Keep going · grade bands mapped to DCU's honours scale
Only your first attempt at each question counts toward this score. Reload the page to reset.
This section contains 20 interactive knowledge checks designed to test your understanding of the materials covered in Chapter 5. The questions cover class architecture, inheritance patterns, dynamic memory (heap vs stack), explicit casting, operator overloading, and separate compilation.
Please remember that many of the quizzes have multiple correct answers , and you must select all applicable options to succeed. I have carefully balanced the lengths of the answers, so take your time to evaluate each option thoroughly.
Good luck!
Derek.
Why is it considered essential to use Member Initialisation Lists when writing constructors in C++? derekmolloy.ie
Because they allow the programmer to explicitly call base class constructors and initialise object members before the constructor body executes.
Because they are the only mechanism available in C++ to assign default values to static global variables.
Because if you do not use them, C++ automatically promotes all private member variables to public scope.
Because they bypass the compiler entirely, injecting values straight into the CPU cache for maximum performance. Submit Answer
Understanding Move Semantics (C++11) derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 class Buffer {
2 int* data;
3 public:
4 // Move Assignment Operator
5 Buffer& operator=(Buffer ····· source) noexcept {
6 if (this != &source) {
7 delete[] data; // Free existing resource
8 data = source.data; // Steal pointer
9 source.data = ····· ; // Leave source in a safe state
10 }
11 return ····· ;
12 }
13 };
Submit
Predict the output: Static Methods vs Instance Methods derekmolloy.ie Read the code below, then choose the terminal output it produces and click Submit.
1 #include <iostream>
2 class Counter {
3 private:
4 static int globalCount;
5 int localCount;
6 public:
7 Counter() : localCount(0) { globalCount++; }
8 void increment() { localCount++; globalCount++; }
9 static int getGlobal() { return globalCount; }
10 int getLocal() const { return localCount; }
11 };
12
13 int Counter::globalCount = 0;
14
15 int main() {
16 Counter a, b;
17 a.increment();
18 b.increment();
19 b.increment();
20 std::cout << Counter::getGlobal() << " " << a.getLocal() << " " << b.getLocal();
21 return 0;
22 }
Submit Answer
Concept Match
Match the Rule of Five/Zero Concept derekmolloy.ie Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.
Definition Pool
Designing classes to use smart pointers and standard containers so you don't need to write any custom memory management methods.
Allocating entirely new memory blocks and duplicating the actual data, rather than just copying pointer addresses.
An operator (operator=) that safely duplicates data from an existing object into an already constructed object.
A method that takes an rvalue reference to efficiently 'steal' resources from a temporary source object.
Submit
In C++, what is the primary distinction between a 'struct' and a 'class'? derekmolloy.ie
Structs cannot participate in inheritance hierarchies or utilize virtual functions.
A struct is purely a data container and cannot have member methods, whereas a class encapsulates both data and methods.
A struct defaults to public access for its members and base classes, whereas a class defaults to private access.
Structs are allocated exclusively on the stack, while classes are always dynamically allocated on the heap. Submit Answer
Constructor Delegation (C++11) derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 class Sensor {
2 int id;
3 int timeout;
4 public:
5 // Main constructor
6 Sensor(int id, int timeout) : id(id), timeout(timeout) {}
7
8 // Delegating constructor
9 Sensor(int id) ····· ····· (id, 5000) {}
10 };
Submit
If you allocate an object dynamically on the heap (e.g., Account* a = new Account()), what happens if you forget to call 'delete a' before the program ends? derekmolloy.ie
The operating system immediately triggers a segmentation fault, terminating the process because of unfreed memory.
The C++ compiler will automatically insert a 'delete' command at the end of the main function to prevent leaks.
The object on the heap safely invokes its own virtual destructor precisely as the program is closing.
The pointer 'a' on the stack is destroyed when it goes out of scope, but the object on the heap remains, causing a memory leak. Submit Answer
Safe Array Allocation and Deallocation derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 int main() {
2 // Dynamically allocate an array of 50 accounts
3 Account* fleet = ····· Account[50];
4
5 // Deallocate the array safely
6 ····· fleet;
7 return 0;
8 }
Available Snippets
new
malloc
free
destroy()
delete
delete[]
Submit
Predict the output: Object Slicing derekmolloy.ie Read the code below, then choose the terminal output it produces and click Submit.
1 #include <iostream>
2 class Base {
3 public:
4 virtual void print() const { std::cout << "Base "; }
5 };
6
7 class Derived : public Base {
8 public:
9 void print() const override { std::cout << "Derived "; }
10 };
11
12 void showValue(Base b) { b.print(); }
13 void showRef(const Base& b) { b.print(); }
14
15 int main() {
16 Derived d;
17 showValue(d);
18 showRef(d);
19 return 0;
20 }
Submit Answer
Why does adding a single 'virtual' method to a C++ class increase the size of every instantiated object by 8 bytes (on a 64-bit system)? derekmolloy.ie
Because the source code of the virtual method is injected directly into the object's memory footprint.
Because the compiler must generate a hidden 'vptr' (vtable pointer) at offset 0 of the object to locate the correct method implementations at runtime.
Because virtual methods automatically double the size of all integer types within the class to prevent arithmetic overflows.
Because the virtual keyword forces the object to be aligned to a 64-byte boundary, injecting massive amounts of padding. Submit Answer
Solving the Diamond Problem derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 class Device {
2 public:
3 virtual void powerOn() = 0;
4 };
5
6 // Virtually inherit from Device
7 class Transmitter : ····· public Device {
8 // ...
9 };
10
11 // Virtually inherit from Device
12 class Receiver : ····· public Device {
13 // ...
14 };
15
16 // Multiple inheritance
17 class Transceiver : public Transmitter, public Receiver {
18 // ...
19 };
Available Snippets
friend
static
virtual
override
virtual
final
Submit
Concept Match
Match the Explicit Cast derekmolloy.ie Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.
Definition Pool
Used specifically to add or remove 'const' qualifiers, though modifying a true constant results in undefined behaviour.
The most dangerous cast, performing simple bit-level reinterpretation between unrelated pointer types.
A type-safe downcast exclusively for polymorphic classes that performs a crucial run-time check.
The standard tool for safe, well-defined conversions verified at compile time (e.g., float to int).
Submit
Using dynamic_cast Safely derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 void checkAccount(Account* acc) {
2 // Attempt a safe downcast
3 CurrentAccount* current = ····· <CurrentAccount*>(acc);
4
5 // Check if the cast succeeded
6 if (current != ····· ) {
7 current->processOverdraft();
8 }
9 }
Available Snippets
static_cast
dynamic_cast
nullptr
void
reinterpret_cast
NULL
Submit
Why is std::bit_cast (C++20) preferred over reinterpret_cast when inspecting the raw bit pattern of a floating-point number? derekmolloy.ie
Because std::bit_cast automatically encrypts the bit pattern using AES-256 for secure transmission.
Because std::bit_cast copies the exact bit pattern safely and can be evaluated at compile time (constexpr).
Because using reinterpret_cast to read a float through an int pointer violates the 'strict aliasing' rule, resulting in Undefined Behaviour.
Because reinterpret_cast is restricted strictly to C-style strings and cannot be used on numeric variables. Submit Answer
The override and final Keywords derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 class Base {
2 public:
3 virtual void process() {}
4 };
5
6 class Derived : public Base {
7 public:
8 // Ensure this correctly overrides a base method
9 void process() ····· ····· {}
10 };
11
12 class Terminal ····· : public Derived {
13 // Cannot inherit from Terminal
14 };
Available Snippets
override
final
virtual
const
static
final
sealed
Submit
Why is std::variant (C++17) recommended over a raw 'union' in modern C++? derekmolloy.ie
Because std::variant is compressed by the compiler, using half the memory footprint of a standard raw union.
Because raw unions are deprecated and will cause modern C++20 compilers to fail with a syntax error.
Because std::variant automatically manages type safety, throwing a std::bad_variant_access exception if you attempt to read the wrong active type.
Because std::variant allows multiple data members to be active and accessed simultaneously. Submit Answer
Which of the following are true regarding the C++ 'friend' keyword? derekmolloy.ie
Friendship is highly contagious; if Class A is a friend of Class B, and Class B is a friend of Class C, then Class A is automatically a friend of Class C.
Friendship is automatically inherited, meaning any class that derives from a friend class also gains full access to private members.
Friendship is commonly used when overloading the stream insertion operator (operator<<) so it can access private data without needing public getters.
A friend function is not a member of the class, but it is explicitly granted access to the class's private and protected members. Submit Answer
Operator Overloading: Post-Increment Drag the tiles to arrange the code in the correct order, then click Submit. Locked lines stay in place. Indentation is dynamically applied based on the location of braces.
Number Number::operator++(int) {Submit Order
Include Guards in Header Files derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 // Prevent multiple definitions (ODR violations)
2 # ····· ROBOT_H
3 # ····· ROBOT_H
4
5 class Robot {
6 // Class definitions
7 };
8
9 # ·····
Available Snippets
undef
include
endif
pragma
ifdef
define
ifndef
Submit
Predict the output: Const Correctness derekmolloy.ie Read the code below, then choose the terminal output it produces and click Submit.
1 #include <iostream>
2
3 class Sensor {
4 int value;
5 public:
6 Sensor(int v) : value(v) {}
7 void read() { std::cout << "M" << value << " "; value++; }
8 void read() const { std::cout << "C" << value << " "; }
9 };
10
11 int main() {
12 Sensor s1(10);
13 const Sensor s2(20);
14
15 s1.read();
16 s1.read();
17 s2.read();
18
19 return 0;
20 }
Submit Answer
Congratulations on completing the Chapter 5 Knowledge Test!
Review any questions you missed to ensure a solid grasp of complex object-oriented design and memory management before advancing to the C++ Standard Library.