Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A C++ class is a user-defined, compound data type that serves as a blueprint for instantiating objects. It enforces encapsulation by binding data members (state) and member functions (behavior) into a single logical unit, while strictly controlling visibility and modification rights through access specifiers.
class ClassName {
    // By default, members are private in a C++ class
    int defaultPrivateMember; 

private:
    // Accessible only from within the class itself or by friend entities
    int privateData;

protected:
    // Accessible within the class and by derived (child) classes
    double protectedData;

public:
    // Accessible from anywhere the object is in scope
    
    // Default Constructor
    ClassName();

    // Parameterized Constructor
    explicit ClassName(int initialValue); 
    
    // Destructor
    ~ClassName(); 

    // Copy Constructor
    ClassName(const ClassName& other);

    // Copy Assignment Operator
    ClassName& operator=(const ClassName& other);

    // Move Constructor
    ClassName(ClassName&& other) noexcept;

    // Move Assignment Operator
    ClassName& operator=(ClassName&& other) noexcept;

    // Member function declaration
    void modifyState(int newValue); 
    
    // Const member function: Guarantees no modification to the object's state
    int getState() const; 
}; // A class definition must terminate with a semicolon

Core Structural Components

Access Specifiers C++ uses private, protected, and public to define the access control model. Unlike a C++ struct where members are public by default, a class defaults to private. This enforces data hiding, requiring external code to interact with the object strictly through its public interface. Special Member Functions and Resource Management The compiler can implicitly generate six special member functions. Managing these functions correctly is governed by the Rule of Zero/Three/Five, which dictates that if a class manually defines a destructor, copy constructor, or copy assignment operator to manage unmanaged resources, it generally must define all of them, including move semantics, to ensure correct value semantics and prevent resource leaks or double-frees. If no manual resource management is needed, rely on the compiler-generated defaults (Rule of Zero).
  • Constructors (ClassName()) are invoked automatically during object instantiation to allocate resources and establish class invariants.
  • Destructors (~ClassName()) are invoked automatically when an object’s lifetime ends. They are critical for releasing unmanaged resources (memory, file handles, network sockets), forming the basis of the RAII (Resource Acquisition Is Initialization) idiom.
  • Copy Semantics (ClassName(const ClassName&) and operator=) define how an object is duplicated. For classes managing dynamic memory, these must be explicitly defined to perform deep copies rather than the default shallow copies.
  • Move Semantics (ClassName(ClassName&&) and operator=) optimize performance by transferring ownership of resources from temporary (rvalue) objects to a new object, avoiding expensive deep copies. They should typically be marked noexcept.
The Implicit this Pointer When a non-static member function is called, the compiler implicitly passes a pointer to the invoking object. Inside the member function, this pointer is accessible via the this keyword. It is passed as a hidden first argument to the function signature at the ABI level.

Method Implementation

Member functions can be defined inline within the class body or out-of-line. Out-of-line definitions require the scope resolution operator (::) to link the implementation to the class declaration.
#include <utility>

// Out-of-line constructor implementation using a member initializer list
ClassName::ClassName(int initialValue) 
    : defaultPrivateMember(0), privateData(initialValue), protectedData(0.0) {
}

// Out-of-line move constructor implementation
ClassName::ClassName(ClassName&& other) noexcept
    : defaultPrivateMember(std::exchange(other.defaultPrivateMember, 0)),
      privateData(std::exchange(other.privateData, 0)),
      protectedData(std::exchange(other.protectedData, 0.0)) {
    // Resources are "stolen" from 'other', leaving 'other' in a valid but unspecified state
}

// Out-of-line destructor implementation
ClassName::~ClassName() {
    // Cleanup code
}

// Out-of-line member function implementation
void ClassName::modifyState(int newValue) {
    this->privateData = newValue; // 'this->' is optional but explicit
}

Instantiation and Memory Allocation

Classes are instantiated into objects. The memory allocation strategy dictates the object’s lifetime and storage location.
#include <memory>

int main() {
    // 1. Stack Allocation (Automatic Storage Duration)
    // Destroyed automatically when execution leaves the current scope.
    ClassName stackObject(10); 

    // 2. Heap Allocation (Dynamic Storage Duration)
    // Returns a pointer. Requires manual deallocation using 'delete'.
    ClassName* heapObject = new ClassName(20);
    delete heapObject; 

    // 3. Smart Pointers (Modern C++ Heap Allocation)
    // Automatically manages heap memory lifecycle via RAII.
    std::unique_ptr<ClassName> smartObject = std::make_unique<ClassName>(30);

    return 0;
}

Memory Layout Mechanics

At runtime, a C++ class instance does not contain its member functions. The size of an object (sizeof(ClassName)) is determined by its non-static data members, plus any padding added by the compiler for memory alignment. However, an empty class (with zero non-static data members) has a minimum size of 1 byte. The compiler enforces this to ensure that distinct objects in an array or memory space have unique, addressable memory locations. If a class contains or inherits virtual functions, the compiler silently injects a hidden pointer (the vptr) into the object’s memory layout. This pointer references a virtual table (vtable) used to resolve dynamic dispatch at runtime, which increases the overall size of the instantiated object by the size of one memory address. Static data members are stored in the program’s global data segment and do not contribute to the sizeof an individual object.
Master C++ with Deep Grasping Methodology!Learn More