Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

C++ Core Concepts and Language Features

Tech May 19 1

Introduction to C++ and Classes

Classes represent a powerful addition to C++'s type system, enabling data encapsulation and information hiding.

Encapsulation refers to bundling related data and operations into a single unit, creating separation from external code. Typically, class data members are declared as private to enforce information hiding. The class mechanism supports core object-oriented principles including encapsulation, information hiding, inheritance, derivation, and polymorphism.

Declaration Placement: Declarations can appear inside functions (local scope limited to that function) or outside functions (global scope).

Compilation Process: The compiler translates source code (.cpp files) into binary object files (.obj), performing lexical and syntax checking. The compiler reports both warnings (non-critical issues) and errors (must-fix issues).

Execution Process: The compiled object code links with system libraries to produce an executable (.exe), which then loads into memory and runs.

Functions and Storage

Function Characteristics:

  • Functions cannot be nested within other functions, but nested calls are permitted
  • Parameters do not occupy memory storage until the function is invoked
  • Default arguments must appear at the rightmost position of the parameter list
  • Default values are specified in function declarations
// Declaration with defaults
int calculate(int width, int height = 10, int depth = 10);

// Valid call: 15, 10, 10
calculate(15);

Function Overloading: Multiple functions may share the same name when their parameter lists differ in count, order, or type.

Storage Classes:

Declaration Category Description
auto Automatic local Local variables within functions (default)
static Static local Stored in static storage area
register Register Frequently-used variables stored in CPU registers
extern External Global variables; enables use before declaration

Static Storage vs Dynamic Storage: Global variables reside in static storage throughout program execution. Dynamic storage contains:

  1. Function parameters (allocated during invocation)
  2. Local variables without static keyword
  3. Return addresses and call context

Pointers and Arrays

Array Parameters: The C++ compilation system treats array parameters as pointer variables.

Row and Column Pointers: Row pointers reference entire rows; column pointers reference specific elements within rows.

a[1][2] == *(*(a + 1) + 2)
// a+1 is a row pointer
// *(a+1) yields the column pointer a[1]
// &a[1] converts back to row pointer

Const Pointers:

Type Behavior Syntax
Pointer to constant Cannot modify pointed-to value; pointer can change const int* ptr;
Constant pointer Can modify pointed-to value; pointer cannot change int* const ptr;
Const pointer to constant Neither can change const int* const ptr;

References: A reference serves as a alias for a variable. Since references are aliases rather than actual variables, constants cannot use references. Internally, references contain variable addresses.

Structures and Enumerations

Structure Rules:

  • Structures cannot contain instances of themselves but can contain pointers to themselves
  • Member initialization within the structure definition is not allowed
  • Structures support constructors but not destructors
  • Structures cannot participate in inheritance
  • Structure instances can be created without new, unlike class objects
  • Passing a structure to a function as a parameter uses pass-by-value

Enumeration Types:

enum ColorScheme { red, green, blue };  // Values: 0, 1, 2

enum Priority { high = 3, medium, low };  // Values: 3, 4, 5

Enumerators are constants that cannot be reassigned but possess implicit integer values starting from zero.

Bitwise XOR: The ^ operator yields 1 when operands differ and 0 when they match.

Object-Oriented Principles

Four Pillars of OOP:

  1. Abstraction: Focusing on essential characteristics
  2. Encapsulation: Grouping data and operations; typically data members are private, interface functions are public
  3. Inheritance: Reusing existing classes to create new derived classes
  4. Polymorphism: Derived class instances respond differently to identical messages

Class Declaration Details:

  • Class declarations end with a semicolon, similar to structs
  • Members default to private if no access specifier is provided
  • Multiple access sections (public/private) can exist within a class
  • Classes lacking member functions behave like structs

Inline Member Functions:

Functions defined inside the class body are automatically treated as inline if they contain no control structures:

class Rectangle {
public:
    inline int area() { return width * height; }  // Optional inline keyword
};

External definitions require explicit inline declaration but separate the interface (.h) from implementation (.cpp).

Memory Layout: Individual objects only store their data members; member functions occupy shared space outside objects.

Constructors and Destructors

Constructor Behavior:

  • Default constructors provide default parameter values
  • Classes and structs both generate parameterless constructors automatically
  • User-defined parameterized constructors replace the default constructor
class Container {
public:
    Container() : width(0), height(0) {}
    Container(int w = 0, int h = 0) : width(w), height(h) {}
};

Destructor Rules:

  • Destructor names begin with ~ followed by the class name
  • Destructors cannot be overloaded (no parameters allowed)
  • Only one destructor per class exists
  • If undefined, the system provides an empty destructor
class ResourceHolder {
public:
    ResourceHolder(int val) { data = new int(val); }
    ~ResourceHolder() { delete data; }
private:
    int* data;
};

Destruction Order: Objects constructed last are destroyed first (LIFO stack behavior).

Static local objects constructed within functions persist until program termination.

The this Pointer

The *this pointer references the object invoking the member function. When calling obj.function(), the this pointer automatically points to obj, enabling access to that object's members.

Constant Objects and Members

Constant Object Declaration:

Type Syntax
Constant object class_name const obj or const class_name obj
Constant data member const data_type member_name
Constant member function return_type function_name(params) const

Constant Object Rules:

  • Constant objects can only invoke const member functions
  • Const member functions can read both const and non-const data but cannot modify any data
  • Non-const member functions cannot be called on constant objects

Constant Pointers:

Type Syntax
Pointer to constant object const class_name* ptr;
Constant pointer to object class_name* const ptr;

When declaring constant pointers (regardless of pointed-to type), const appears within the declaration.

Object Copying and Assignment

Copy Constructor: Creates a new object identical to an existing one.

class Box {
public:
    Box(const Box& original);  // Copy constructor signature
};

Box newBox = existingBox;  // Invokes copy constructor
Box anotherBox(existingBox);  // Also invokes copy constructor

If undefined, the system provides a default copy constructor.

Assignment Operator: Assigns values to an existing object. Class data members should not include dynamically-allocated memory pointers, as this causes issues during deletion.

Static Members

Static Data Members:

  • Declared with static keyword within the class
  • Initialized out side the class (mandatory)
  • Cannot use initializer lists
  • Default value is zero if uninitialized
  • Public static members are accessible via class name or object name
  • Private static members require member function access
  • Static member scope is limited to the class
class BankAccount {
private:
    static double interestRate;  // Declaration
public:
    static int instanceCount;
};

double BankAccount::interestRate = 0.05;  // Definition

Static Member Functions:

  • Lack the this pointer
  • Can only access static members of their class
  • Declared with static keyword

Friend Functions and Classes

Friend functions gain access to private members of the class that declares them as friends. Since friend functions lack the this pointer, object names must be specified when accessing members:

class Triangle {
    friend void display(Triangle& t);
};

void display(Triangle& t) {
    cout << t.sideLength;  // Object reference required
}

Friend classes grant all member functions of one class access to another class's private members.

Operator Overloading

Overloading Rules:

  • Overloaded functions must differ in parameter count, order, or type
  • Overloaded operators cannot have default arguments
  • At least one parameter must be a user-defined type
  • operator<< and operator>> must be friend functions (not members), as their left operands are stream types
class Complex {
    friend Complex operator+(const Complex& left, const Complex& right);
    friend ostream& operator<<(ostream& out, const Complex& obj);
};

Conversion Constructors: Convert basic types or other class objects into the current class type. These constructors accept exactly one parameter.

Type Conversion Functions: Convert the current class object to another type.

class Temperature {
public:
    operator double() { return celsiusValue; }  // Converts to double
};

Caution: Having both conversion constructors and type conversion functions can introduce ambiguity.

Inheritance and Derivation

Class Relationships:

  • If class B inherits from class A, then A is the base/parent/superclass and B is the derived/child subclass
class DerivedClass : [access_mode] BaseClass {
    // New members specific to derived class
};
// access_mode: public, protected, private (default is private)

Inherited Members: All base class members are inherited except constructors and destructors.

Member Overriding: When derived class members share names with base class members, the derived version takes precedence (shadowing).

Access Control Table:

Base Member Public Derivation Protected Derivation Private Derivation
public public protected private
protected protected protected private
private inaccessible inaccessible inaccessible

Memory Layout: Derived class instances contain their own non-static data members plus inherited non-static members. Static members and member functions exist once per class hierarchy.

Derived Class Constructors:

Constructor execution order:

  1. Call base class constructor
  2. Call member object constructors
  3. Execute derived class constructor

Destructor execution follows reverse order.

class Person {
protected:
    string name;
    int age;
public:
    Person(string n, int a) : name(n), age(a) {}
};

class Employee : public Person {
private:
    int employeeId;
public:
    Employee(string n, int a, int id) : Person(n, a), employeeId(id) {}
};

For simple derived classes without member objects, base class data members should be protected (not private) to allow access from derived constructors.

Multiple Inheritance:

class Derived : public Base1, public Base2 {
    // Members from both base classes
};

Ambiguity Resolution: When base classes share members with identical names:

class Graduate : public Teacher, public Student {
    // Both Teacher and Student have 'name' member
};

Graduate g;
g.Teacher::name;  // Access Teacher's name

Virtual Base Classes: Prevent duplicate copies of base class members in multiple inheritance scenarios:

class Base {
protected:
    int sharedValue;
public:
    Base(int v) : sharedValue(v) {}
};

class BranchA : virtual public Base {
public:
    BranchA(int v) : Base(v) {}
};

class BranchB : virtual public Base {
public:
    BranchB(int v) : Base(v) {}
};

class Final : public BranchA, public BranchB {
public:
    Final(int v) : Base(v), BranchA(v), BranchB(v) {}
};

With virtual base classes, only the most derived class (Final) initializes the shared base class member.

Assignment Compatibility: A derived class instance can be assigned to a base class variable, but this discards the derived-specific portions. Base class pointers can reference derived class objects to access base members.

Polymorphism and Virtual Functions

Polymorphism Types:

Type Resolution Time Implementation Purpose
Static Compile-time Function overloading Same-level functions with different signatures
Dynamic Runtime Virtual functions Same function across inheritance hierarchy

Virtual Functions: Declared with the virtual keyword in the base class and redefined in derived classes.

class Shape {
public:
    virtual double area() const { return 0; }
};

class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    double area() const override { return 3.14159 * radius * radius; }
};

Virtual functions enable base class pointers and references to invoke appropriate derived class implementations dynamically.

Important Rules:

  • Without virtual keyword, base class pointer calls base class members only
  • Derived class virtual functions become virtual automatically
  • Virtual functions cannot be constructors but should be destructors
  • Declaring base class destructors as virtual ensures proper cleanup when deleting derived objects through base pointers

Pure Virtual Functions: Declare virtual functions without implementations:

virtual double volume() const = 0;

Abstract Classes: Classes containing pure virtual functions cannot be instantiated. They serve as interface specifications for derived classes.

class Geometry {
public:
    virtual double calculate() const = 0;
    virtual ~Geometry() {}  // Virtual destructor
};

Derived classes must implement all pure virtual functions to become instantiable. Abstract class pointers can reference derived class objects to achieve polymorphic behavior.

Input and Output Streams

I/O Categories:

  1. Standard I/O: Input/output to system devices
  2. File I/O: Input/output to storage media
  3. String I/O: Input/output to memory buffers

Stream Class Hierarchy:

Class Purpose Header
ios Abstract base class -
istream Input stream base -
ostream Output stream base iostream
iostream Combined input/output -
ifstream Input file stream fstream
ofstream Output file stream fstream
fstream Bidirectional file stream fstream
istrstream Input string stream strstream
ostrstream Output string stream strstream

Standard Output Objects:

  • cout: Buffered output; endl flushes the buffer and outputs a newline
  • cerr: Unbuffered error output to standard error device
  • clog: Buffered error output; flushes when buffer fills or at program end

Standard Input Object:

  • cin: Extractions (>>) skip whitespace characters
  • Input requires pressing Enter before processing
  • Returns zero in boolean context when encountering EOF or errors

Character Input Methods:

cin.get();           // Read single character including whitespace
cin.get(ch);         // Read into character variable
cin.get(buffer, n);  // Read n-1 characters
cin.getline(buffer, n);  // Read line, skip delimiter in next read
cin.ignore(n, delim);    // Skip n characters or until delimiter
cin.peek();          // View next character without consuming
cin.putback(ch);     // Return character to input stream

File End Detection:

while (!cin.eof()) {  // Continue until end of file
    // Process input
}

Exception Handling

Exception Flow:

  1. Program execution proceeds normally through the try block
  2. When an exception occurs, the program searches for a matching catch block
  3. If no catch exists in the current function, the search continues in calling functions
  4. After handling, execution continues after the catch blocks
  5. Uncaught exceptions terminate the program
try {
    // Normal execution path
    if (errorCondition) {
        throw value;
    }
} catch (int errorCode) {
    // Handle integer exceptions
} catch (const char* message) {
    // Handle string exceptions
}

Function Pointers

Obtaining Function Addresses: The function name itself represents its adress in memory.

Declaration Syntax: Function pointer declarations specify both the return type and parameter signature:

double calculate(int value);
double (*functionPtr)(int);  // Pointer to function returning double

functionPtr = calculate;  // Store function address

Function pointers enable passing behavior as arguments, allowing functions to call different operations based on runtime decisions.

Tags: C++

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.