C++ CPE study materials
C++ CPE study resources

C++ CPE: C++ Essentials 2 (CPP102 / CPPE2): Classes, Polymorphism, Templates, and STL

C++ CPE · Work through your exam, one topic at a time.

All guide sections

C++ Essentials 2 (CPP102 / CPPE2): Classes, Polymorphism, Templates, and STL

The C++ Essentials 2 (CPP102 / CPPE2) domain tests class-based and generic C++: special member functions, construction/destruction order, inheritance and dynamic polymorphism, operator overloading, exceptions, templates, and core STL usage. Questions often present a small hierarchy or container operation and ask which function runs, which object is copied, or what remains valid afterward.

Class mechanics and special members

  • Non-static data members initialize in declaration order, not in the order of the constructor initializer list.
  • The compiler generates copy/move constructors, copy/move assignment, and a destructor when viable; a user-declared destructor or copy operation can suppress implicit move generation.
  • = default, = delete, and explicit control special-member generation and implicit conversions.
  • The rule of three/five/zero: if a class manages a resource, define or delete the operations consistently.

Inheritance and dynamic polymorphism

  • A function is polymorphic only when called through a pointer or reference to a base and the function is virtual.
  • override makes an intended override a compile-time error if no matching base virtual exists; final prevents further overriding.
  • Deleting a derived object through a base pointer requires a virtual destructor; otherwise the behavior is undefined.
  • Passing a derived object by value to a base parameter slices it: only the base subobject is copied.

Templates and STL

  • Class/function templates are instantiated on use; each distinct argument type produces a distinct specialization.
  • STL containers own their elements; iterators are invalidated by operations such as vector::push_back that reallocate.
  • Algorithms take iterator ranges [first, last); lambdas capture by value [=] or by reference [&].

Worked example

struct Base {
    virtual ~Base() = default;
    virtual int f() const { return 1; }
};
struct Derived : Base {
    int f() const override { return 2; }
};
void call(const Base& b) { std::cout << b.f(); }
int main() {
    Derived d;
    call(d);          // prints 2
    Base b = d;       // slices
    std::cout << b.f(); // prints 1
}

call(d) binds a const Base& to the Derived object; f is virtual, so dispatch reaches Derived::f. Base b = d copies only the Base subobject, so the dynamic type is Base and f returns 1.

Traps that cost marks

  • Expecting initializer-list order to set initialization order.
  • Forgetting a virtual destructor before deleting through Base*.
  • Slicing when passing by value.
  • Using an iterator after a reallocating container operation.
  • Letting an exception escape a destructor during stack unwinding (std::terminate).