Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Advanced C++ Programming: From Fundamentals to Polymorphism

Tech 1

Development Environment and Project Configuration

When managing multiple source files within a single C++ project using CMake, you can automate the generation of executables for each .cpp file found in the source directory. This is particularly useful for competitive programming or educational modules.

# Locate all .cpp files recursively
file(GLOB_RECURSE source_files *.cpp)

# Generate an executable for every detected source file
foreach(src_file ${source_files})
    string(REGEX REPLACE ".+/(.+)\\..*" "\\1" bin_name ${src_file})
    add_executable(${bin_name} ${src_file})
    message(STATUS "Compiling ${src_file} into binary: ${bin_name}")
endforeach()

Data Types and Memory Footprint

Integer and Float Precision

The sizeof operator is essential for determining the memory allocation of different data types in bytes. C++ distinguishes between signed and unsigned integers; unsigned types are restricted to non-negative values, effectively doubling the positive range for the same byte size.

Floating-point precision in C++ typically provides 7 significant digits for float. When outputting large values or precise decimals, using std::fixed and std.precision ensures accuracy in display.

#include <iostream>
#include <iomanip>

int main() {
    float pi_approx = 3.1415926535f;
    // Set precision and fixed notation
    std::cout << std::fixed << std::setprecision(5) << pi_approx << std::endl;
    return 0;
}

Character and String Representation

Characters in C++ are mapped to the ASCII table. Internally, a char is an integer. Strings can be managed via C-style character arrays or the more robust std::string class.

C++ Memory Management Model

C++ applications segment memory into four distinct areas to manage data lifecycles effectively:

  1. Code Area: Stores the binary instructions executed by the CPU. This area is read-only and shared among process instances.
  2. Global Area: Contains global variables, static variables, and constants. This memory is managed by the OS and released only when the program terminates.
  3. Stack Area: Managed by the compiler. It stores local variables and function parameters. Memory is automatically allocated and deallocated as functions enter and exit scope.
  4. Heap Area: Managed by the programmer via new and delete operators. If memory is not manually freed, the OS reclaims it upon program exit.
int* heap_ptr = new int(100); // Allocate on heap
delete heap_ptr;              // Manual release
heap_ptr = nullptr;           // Prevent dangling pointer

References and Functions

A reference acts as an alias for an existing varible. Unlike pointers, references must be initialized upon declaration and cannot be redirected to another variable later. Internally, a reference is implemented as a constant pointer (Type * const ptr).

Reference Parameters and Returns

Passing by reference is more efficient than passing by value as it avoids copying large objects. How ever, returning a reference to a local stack variable is a critical error, as that memory is destroyed once the function returns.

void swap_values(int &val1, int &val2) {
    int temp = val1;
    val1 = val2;
    val2 = temp;
}

Object-Oriented Programming: Encapsulation

C++ uses class and struct to encapsulate data and behavior. The primary difference is the default access level: struct defaults to public, while class defaults to private.

  • Public: Accessible from anywhere.
  • Protected: Accessible within the class and its subclasses.
  • Private: Accessible only within the class itself.

Constructor and Destructor Lifecycle

Constructors initialize objects, while destructors perform cleanup. If a class allocates heap memory, you must implement a Deep Copy in the copy constructor to ensure that each object owns a unique memory buffer, preventing double-deletion errors.

class DataContainer {
public:
    int* m_buffer;
    DataContainer(int size) {
        m_buffer = new int(size);
    }
    // Deep Copy Constructor
    DataContainer(const DataContainer& other) {
        m_buffer = new int(*other.m_buffer);
    }
    ~DataContainer() {
        delete m_buffer;
    }
};

This Pointer and Const Members

The this pointer is an implicit parameter in non-static member functions, pointing to the object instance. When a member functon is marked as const, it cannot modify non-mutable member variables.

Operator Overloading

Operator overloading allows custom types to use standard operators like +, <<, and ++. Binary operators are often overloaded as member functions, while operators like << (output stream) must be global to allow the std::ostream object to appear on the left side.

// Overloading prefix increment
MyInt& operator++() {
    this->m_val++;
    return *this;
}

// Overloading postfix increment using a dummy int parameter
MyInt operator++(int) {
    MyInt temp = *this;
    this->m_val++;
    return temp;
}

Inheritance and Polymorphism

Inheritance allows a subclass to acquire the properties of a base class. C++ supports public, protected, and private inheritance, which determines the access level of inherited members in the derived class.

Polymorphism and Virtual Functions

Polymorphism allows a base class pointer or reference to invoke behavior specific to a derived class at runtime. This is achieved through virtual functions and the Virtual Function Table (V-Table).

class Shape {
public:
    virtual void draw() { std::cout << "Drawing Shape" << std::endl; }
    virtual ~Shape() {} // Virtual destructor is vital for cleanup
};

class Circle : public Shape {
public:
    void draw() override { std::cout << "Drawing Circle" << std::endl; }
};

void render(Shape& s) {
    s.draw(); // Dynamic binding
}

Pure Virtual Functions and Abstract Classes

A class becomes abstract if it contains at least one pure virtual function (virtual void func() = 0;). Abstract classes cannot be instantiated and serve as blueprints for derived classes.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.