Answers generated with AI, please use other resources alongside to confirm accuracy.
| Question | Answer |
|---|---|
| 1. What are the default operators that are overloaded for classes? | The compiler supplies default behavior for assignment operator = and member access through pointers -> where appropriate. In practice, the key default one discussed for classes is the assignment operator =. |
| 2. What are the overloading restrictions? | You cannot change precedence, associativity, or number of operands. You cannot create new operators. You also cannot change how operators work for built-in types. Operators that cannot be overloaded include ., .*, ::, ?:, and sizeof. |
| 3. What does return *this; do? | this is a hidden pointer to the current object. *this dereferences it to the current object itself. Returning *this returns the current object (usually by reference), which supports chaining. |
| 4. What is a friend function? | A friend function is a non-member function that has permission to access a class's private and protected members. It is declared with the friend keyword inside the class declaration. |
| 5. What is the difference between overloading as a member function vs non-member function? | A member operator function has the left operand bound to the class object (*this). A non-member (often friend) function receives both operands explicitly and is useful when the left operand is not a class object. |
| 6. What is special about overloading stream operators << and >>? | Because the left operand is stream object (like cout or cin), these operators are typically overloaded as non-member functions (often friends), not member functions of your class. |
| 7. When do we need to overload assignment operator = and why? | You need to overload = when a class manages dynamic memory or other owned resources (for example, pointer data members). The default assignment does shallow copy and can cause aliasing, double deletion, or leaks. |
| 8. How do we overload pre-increment and post-increment operators? | Pre-increment uses operator++() with no dummy parameter. Post-increment uses operator++(int) where int is an unused dummy parameter to distinguish it from pre-increment. |
| 9. What is special about overloading the [] index operator? | It is commonly overloaded in two versions: a non-const version returning Type& for modifiable objects, and a const version returning const Type& for read-only access on const objects. |
| 10. How are templates like overloading, and how are they different? | Both support generic behavior across multiple types. Overloading writes multiple explicit function versions, while templates define one generic pattern and the compiler generates concrete versions for specific types. |
| 11. What is a class template, and what does it allow you to do? | A class template lets you write one class blueprint parameterized by type(s), so you can create related classes for many data types without duplicating class code. |
| 12. What is special about how class templates must be compiled? | Template definitions must be visible at compile time where they are instantiated. That is why template methods are usually defined in header files, or in a separate implementation file included at the bottom of the header. |
| Question | Answer |
|---|---|
| 1. What are some examples of exceptions? Are there ever compile-time exceptions? | Common runtime exceptions include divide by zero, null pointer use, and array index out of bounds. Exceptions are primarily a runtime mechanism; compile-time problems are typically reported as compiler errors, not caught exceptions. |
| 2. How do try and catch blocks work? Does catch order matter? What does try surround? What happens after an exception is thrown? | The try block surrounds code that might throw. If an exception is thrown, normal flow stops immediately in that try block and control jumps to the first matching catch. Catch order matters: more specific types should come before more general ones. Without handling, the program may terminate. |
| 3. What does stack unwinding mean when throwing exceptions? | Stack unwinding means the runtime walks back up the call stack after an exception is thrown, destroying local objects in each function scope until a matching catch handler is found. |
| 4. Can you catch and rethrow an exception? Can you throw a different one? | Yes. You can rethrow the current exception with throw; and you can throw a different exception object after handling or translating context. |
| 5. What header do you need for system-defined exceptions? What header for your own exceptions? | System-defined standard exception classes are commonly from <stdexcept>. For defining custom exception types with base exception behavior, include <exception> (and often <stdexcept> depending on the base class you choose). |
| 6. How do you define your own exceptions? | Create a custom class that inherits from a standard exception base (such as std::exception or a std::runtime_error family type), then optionally override what() or provide constructors/data as needed. |
| 7. Should you define your own exceptions or use existing ones? | Prefer standard exceptions when they fit. Define custom exceptions when domain-specific meaning or additional context is needed. |
| 8. Why inherit custom exceptions from the standard exception hierarchy? | Inheritance keeps your exceptions compatible with standard catch patterns and polymorphic handling, and integrates well with existing C++ libraries and tools. |
| 9. When should custom exceptions be in their own .h/.cpp files? | Place them in separate files when reused across multiple source files or modules. For small one-off exceptions, local definitions can be acceptable. |
| Question | Answer |
|---|---|
| 1. What two conditions must be met for a problem to be solved recursively? | You need a base case (stopping condition) and a recursive case that reduces the problem toward that base case. |
| 2. Define direct recursion, indirect recursion, and tail recursion. | Direct recursion: a function calls itself. Indirect recursion: function A calls function B, which eventually calls A again. Tail recursion: the recursive call is the final operation in the function. |
| 3. Why can iteration be better than recursion for many problems? | Recursion uses additional call stack frames per call, which can increase memory use and risk stack overflow for deep recursion. Iteration is often more memory-efficient and sometimes faster. |
| 4. What was the problem with the first recursive Fibonacci solution? | It recomputed the same subproblems repeatedly, causing exponential time complexity and poor performance. |
| 5. How do you trace simple recursive functions? | Follow calls down until reaching the base case, then evaluate returns as the call stack unwinds back to the original call. |