CPA-21-02 Sample Questions & Answers
Object-oriented principles, class definitions, constructors and destructors carry the heaviest weight, alongside pointer declarations and arithmetic, overloaded function basics, exception handling in control-flow statements, and ternary, binary and unary operators.
Launch the full CPA-21-02 simulator →Showing 10 of 20 free samples.
- Question 1Beginner
Classes & Namespaces · Compiler-generated special member functions
True or False: In C++, if a class has a user-defined destructor, the compiler will no longer implicitly generate a default constructor.
Show answer & explanation
Correct answer: B
This statement is false. The presence of a user-defined destructor does not prevent the compiler from generating a default constructor. However, if a user declares any constructor (e.g., a copy constructor or a constructor with parameters), the compiler will then refrain from generating the default constructor.
- Question 2Intermediate
Classes & Namespaces · Virtual destructors and polymorphic deletion
Case Study: A Game Development Studio
A game development studio is creating a new 3D rendering engine. The engine needs to manage various types of game objects, such as
Player,Enemy, andScenery. Each object has a position in 3D space, but also contains type-specific data and behavior. For performance reasons, all game objects are stored in a singlestd::vectorand are updated and rendered in a tight loop.Current Situation
The initial design has a
GameObjectbase class with virtual functions forupdate()andrender(). When aGameObjectis destroyed (e.g., an enemy is defeated), its memory must be reclaimed. The team has observed occasional crashes and memory corruption issues during long gameplay sessions, particularly when large numbers of objects are created and destroyed rapidly.Requirements
- The system must correctly manage the lifecycle of all derived
GameObjecttypes. - When an object is deleted through a
GameObject*pointer, the complete object, including derived parts, must be destroyed. - The design should be extensible to allow for new
GameObjecttypes in the future without modifying the main game loop. - The cause of the memory corruption must be eliminated.
Proposed Code Snippet
class GameObject { public: // Constructor and other members... virtual void update() = 0; virtual void render() = 0; // Missing destructor }; class Enemy : public GameObject { ... }; // In game loop: delete allGameObjects[i]; // i is the index of the object to be removedWhich change is most critical to fix the memory corruption and meet the design requirements?
Show answer & explanation
Correct answer: C
The most critical issue is the lack of a virtual destructor in the polymorphic base class
GameObject. Whendeleteis called on a base class pointer (GameObject*), if the destructor is not virtual, only the base class destructor is invoked. This leads to undefined behavior because the derived class's destructor (e.g.,~Enemy()) is never called, and resources owned by the derived class are not released. This is a classic cause of memory corruption and leaks in C++. Declaring the base class destructor asvirtualensures that the entire object hierarchy is destroyed correctly. - The system must correctly manage the lifecycle of all derived
- Question 3Beginner
Types & Operators · Bitwise AND operator
What is the decimal value of the variable
resultafter the following code executes?int flags = 0b10110; // 22 in decimal int mask = 0x1A; // 26 in decimal, 0b11010 in binary int result = flags & mask;Show answer & explanation
Correct answer: C
The bitwise AND operation (
&) compares the bits of two numbers. A bit in the result is set to 1 only if the corresponding bits in both operands are 1.flags(0b10110)mask(0b11010)result(0b10010)The binary value
0b10010is calculated as (1 * 16) + (0 * 8) + (0 * 4) + (1 * 2) + (0 * 1), which equals 16 + 2 = 18. - Question 4Intermediate
Pointers · Passing arrays to functions
A programmer needs to write a function that accepts an array of integers and its size, and it must modify the original array elements by doubling their value. Which function signature is the most appropriate and conventional C++ approach for this task?
Show answer & explanation
Correct answer: C
In C++, when an array is passed to a function, it decays into a pointer to its first element. To modify the original array's contents, the function must accept a pointer to the element type.
int* arris the idiomatic way to declare a parameter that accepts an array of integers. The function can then use pointer arithmetic or array subscripting to access and modify the elements. Avoidreturn type is appropriate as the modifications are done in-place. - Question 5Intermediate
Types & Operators · Ternary operator and side effects
What is the final value of
xafter the following code snippet is executed?int x = 10; int y = 5; x = (y > 3) ? ( (y 0) ? ++y : --y );Show answer & explanation
Correct answer: B
The expression is evaluated as follows:
- The outer condition
(y > 3)is checked. Sinceyis 5, this is true. - The true-branch of the outer ternary is evaluated:
( (y < 10) ? y++ : y-- ). - The inner condition
(y < 10)is checked. Sinceyis 5, this is true. - The true-branch of the inner ternary is evaluated:
y++. - The post-increment operator
y++returns the current value ofy(which is 5) and then incrementsyto 6. - The value 5 is assigned to
x.
- The outer condition
- Question 6Beginner
Functions & Preprocessor Directives · Recursion
A developer needs to create a function that calculates the factorial of a number. They have decided to use recursion. Which of the following implementations is correct and handles a base case appropriately?
Show answer & explanation
Correct answer: B
A recursive function must have a base case to terminate the recursion. For a factorial calculation, the base case is that the factorial of 0 or 1 is 1. This implementation correctly checks for
n 1, it correctly performs the recursive stepn * factorial(n - 1). - Question 7Intermediate
Classes & Namespaces · Friend functions
A class
DataProcessoris designed to handle sensitive information. To log internal state for debugging purposes, a free functionlogInternalStateneeds access to the private members ofDataProcessor. Which mechanism should be used to grant this access without exposing the members publicly?Show answer & explanation
Correct answer: D
The
friendkeyword is the C++ mechanism for granting a non-member function or another class access to theprivateandprotectedmembers of a class. By adding the declarationfriend void logInternalState(const DataProcessor&);inside theDataProcessorclass, thelogInternalStatefunction is allowed to accessDataProcessor's private members while still maintaining encapsulation for all other non-friend functions. - Question 8Beginner
Control & Exceptions · Switch statement fall-through
What is the output of the following C++ code that demonstrates the behavior of a
switchstatement?#include int main() { int value = 2; switch (value) { case 1: std::cout << "A"; case 2: std::cout << "B"; case 3: std::cout << "C"; break; default: std::cout << "D"; } return 0; }Show answer & explanation
Correct answer: B
Execution begins at the matching
case 2:. Since there is nobreakstatement incase 2:, execution "falls through" to the next case,case 3:. The code incase 3:is executed, and then thebreak;statement is encountered, which terminates theswitchblock. Therefore, the output is "BC". - Question 9Beginner
Classes & Namespaces · Namespace aliases
A developer wants to use a single namespace for a collection of utility functions but also wants to provide a shorter, more convenient alias for it within a specific implementation file. Which of the following code snippets correctly defines a namespace
StringUtilsand creates an aliasSUfor it?Show answer & explanation
Correct answer: A
The correct syntax for creating a namespace alias in C++ is
namespace alias_name = original_namespace_name;. This creates a synonym for the namespace, which can be useful for shortening long namespace names or for versioning. - Question 10Intermediate
Pointers · Dynamic memory allocation for arrays
What is the primary difference between
delete ptranddelete[] ptrwhen managing dynamically allocated memory?Show answer & explanation
Correct answer: B
It is critical to match the deallocation form with the allocation form.
new Tallocates a single object and must be freed withdelete.new T[N]allocates an array ofNobjects and must be freed withdelete[]. Using the wrong form (e.g.,deleteon an array) results in undefined behavior. For non-trivial types (classes with destructors), this typically leads to only the first object's destructor being called, causing resource leaks.
Ready for the real thing?
The full CPA-21-02 simulator has every exam-style question, timed mode, and instant scoring.