Object-Oriented Programming and C++
C++ Tokens, Operators, Parameter Passing and Virtual Functions
- C++ adds reference parameters (
int &x) to C's call-by-value: a reference is an alias for the caller's variable, sovoid inc(int &x) { x++; }DOES modify the caller's variable directly — no explicit pointer/dereference needed, unlike plain C. - Virtual functions: declaring a base-class method
virtualmakes calls through a base pointer/reference dispatch to the most-derived override at run time; apure virtualfunction (= 0) has no base implementation at all and makes the class abstract. - Constructors and destructors: a constructor runs automatically at object creation (initialising members, often via an initialiser list for efficiency and for members that must be set once, like references and const fields); a destructor runs automatically at destruction (releasing resources) — a virtual destructor is required on any base class meant to be deleted through a base pointer, or the derived part's destructor is skipped, leaking its resources.
Overloading, Templates, Exception Handling and Streams
- Operator overloading gives operators (
+,<<,==) new meanings for user-defined types — it never changes an operator's precedence or associativity, only what code runs for a given type combination. - Templates give compile-time generic programming: a function or class template is instantiated by the compiler for each concrete type it is actually used with, generating type-specific code with no run-time type-dispatch overhead — distinct from run-time polymorphism, which pays a vtable-lookup cost per call.
- Exception handling:
try/catch/throwseparates error-detection code from error-HANDLING code; an exception thrown inside atryblock unwinds the stack (running destructors of local objects along the way) until a matchingcatchhandler is found, or the program terminates if none is. - Streams and files:
cin/cout/cerrare the standard-stream objects overloading>>/<<;ifstream/ofstreamextend the same stream abstraction to files, so file I/O uses the identical>>/<<syntax as console I/O.
Multifile Programs
A large C++ program is split into a header file (.h, declarations only — class definitions, function prototypes) included wherever needed, and one or more source files (.cpp, actual definitions), compiled separately into object files and combined by the linker. Header guards (#ifndef/#define/#endif, or #pragma once) prevent the same header's declarations from being processed twice if it is (directly or transitively) included more than once in one translation unit — without them, a class or function would appear 'redefined' to the compiler.
Key takeaways
- Class is the blueprint, object the instance; encapsulation hides representation behind an interface; inheritance models IS-A; polymorphism is one interface with many implementations, compile-time (overloading) or run-time (virtual functions).
- Run-time polymorphism fires only through a base-class pointer/reference; calling through a plain base object slices off the derived part.
- A base class deleted through a base pointer needs a virtual destructor, or the derived part's cleanup is skipped.
- Templates are compile-time generics (no run-time dispatch cost); virtual functions are run-time polymorphism (a vtable-lookup cost per call) — different mechanisms for different needs.
- Header guards prevent a header's declarations from being processed twice in one translation unit.
Practice questions (8)
Attempt each one before opening the answer. Every explanation names the tempting wrong option as well as the right one, because that is where marks are lost.
Run-time polymorphism in C++ is triggered when a virtual method is called through:
Show answer
Answer: A — A base-class pointer or reference bound to a derived object
Calling through a base pointer/reference looks up the object's actual dynamic type via the vtable; calling through a plain base object instead slices off the derived part and always invokes the base version.A class containing at least one pure virtual function is:
Show answer
Answer: A — Abstract, and cannot be instantiated directly
A pure virtual function (declared with = 0) has no implementation in that class, so an object of it alone would be incomplete — such a class exists only to be derived from, and derived classes must implement the pure virtual function to become instantiable themselves.Compile-time polymorphism in C++ is achieved through:
Show answer
Answer: A — Function/operator overloading, resolved by argument types at compile time
Overload resolution happens entirely at compile time based on the number and types of arguments; virtual functions, by contrast, are resolved at run time based on the object's actual type — the run-time polymorphism mechanism.A base class from which objects are deleted through base-class pointers should have:
Show answer
Answer: A — A virtual destructor
Without a virtual destructor, deleting a derived object through a base pointer runs only the base class's destructor, skipping the derived part's cleanup and leaking any resources it held.A C++ function template, compared to a virtual function, achieves polymorphism at:
Show answer
Answer: A — Compile time, with no run-time dispatch overhead
The compiler instantiates a separate, type-specific version of the template for each type it is used with, so the correct code is selected entirely at compile time with no run-time type-dispatch cost, unlike virtual functions.When an exception is thrown inside a try block and no matching catch handler exists in the current function:
Show answer
Answer: A — The stack unwinds further, running local destructors, in search of a matching handler up the call chain
Stack unwinding continues up the call chain, destroying local objects along the way, until a matching handler is found somewhere up the chain, or the program terminates (typically via std::terminate) if none exists anywhere.Which of the following are true of C++ reference parameters, as distinct from plain C pointer parameters? (More than one option may be correct.)
Show answer
Answer: A — A reference is an alias for the caller's variable and needs no explicit dereference operator inside the function; B — Modifying a reference parameter modifies the caller's original variable
A reference is bound once at initialisation and cannot be reseated, and (unlike a pointer) a well-formed reference cannot be null, so no null-check is idiomatically needed — it is exactly these two properties that make it an alias rather than an address-holding variable.Name the preprocessor mechanism (three directives, or a single non-standard-but-widely-supported pragma) used to prevent a header file's contents from being processed more than once in one translation unit.
Numerical answer — type the value.
Show answer
Answer: header guard
An #ifndef/#define/#endif header guard (or the #pragma once shortcut most compilers support) prevents a class or function from appearing 'redefined' when the same header is included, directly or transitively, more than once.