Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Operator Overloading and Inheritance in C++

Tech 1

1. Increment Operator Overloading

  • Pre-increment returns a reference, while post-increment returns a value.
// Custom integer class
class CustomInt {
    friend std::ostream& operator<<(std::ostream& output, CustomInt value);
public:
    CustomInt() : data(0) {}
    
    // Pre-increment operator overloading
    CustomInt& operator++() {
        ++data;
        return *this;
    }
    
    // Post-increment operator overloading
    // The int parameter is a placeholder to differentiate from pre-increment
    CustomInt operator++(int) {
        CustomInt temp = *this;
        ++data;
        return temp;
    }
    
private:
    int data;
};

// Overload left shift operator
std::ostream& operator<<(std::ostream& output, CustomInt value) {
    output << value.data;
    return output;
}

void testPreIncrement() {
    CustomInt num;
    std::cout << ++num << std::endl;
}

void testPostIncrement() {
    CustomInt num;
    std::cout << num++ << std::endl;
    std::cout << num << std::endl;
}

int main() {
    testPostIncrement();
    return 0;
}

2. Assignment Operator Overloading

C++ compiler automatically provides at least four functions for a class:

  • Default constructor (no parameters, empty body)
  • Default destructor (no parameters, empty body)
  • Default copy constructor (copies property values)
  • Assignment operator operator= (performs value copy)

If a class has properties pointing to heap memory, assignment operations can lead to shallow vs. deep copy issues.

class Person {
public:
    Person(int age) {
        agePtr = new int(age);
    }
    
    ~Person() {
        if (agePtr != nullptr) {
            delete agePtr;
            agePtr = nullptr;
        }
    }
    
    // Overload assignment operator
    Person& operator=(Person& other) {
        // Compiler provides shallow copy: agePtr = other.agePtr;
        
        // Deep copy implementation
        if (agePtr != nullptr) {
            delete agePtr;
            agePtr = nullptr;
        }
        agePtr = new int(*other.agePtr);
        return *this;
    }
    
    int* agePtr;
};

void testAssignment() {
    Person person1(18);
    Person person2(20);
    Person person3(40);
    person3 = person2 = person1;  // Chained assignment
    std::cout << *person1.agePtr << std::endl;
    std::cout << *person2.agePtr << std::endl;
    std::cout << *person3.agePtr << std::endl;
}

3. Relational Operator Overloading

class Person {
public:
    Person(std::string name, int age) : personName(name), personAge(age) {}
    
    // Overload equality operator
    bool operator==(Person& other) {
        return (personAge == other.personAge && personName == other.personName);
    }
    
    // Overload inequality operator
    bool operator!=(Person& other) {
        return !(*this == other);
    }
    
    std::string personName;
    int personAge;
};

void testComparison() {
    Person person1("Tom", 18);
    Person person2("Tom", 18);
    if (person1 == person2) {
        std::cout << "Equal" << std::endl;
    } else {
        std::cout << "Not equal" << std::endl;
    }
}

4. Function Call Operator Overloading

  • The function call operator () can be overloaded.
  • When overloaded, it resembles a function call, hence called a functor.
  • Functors are flexible with no fixed implementation pattern.
class Printer {
public:
    // Overload function call operator
    void operator()(std::string text) {
        std::cout << text << std::endl;
    }
};

void printFunction(std::string text) {
    std::cout << text << std::endl;
}

void testPrinter() {
    Printer printer;
    printer("Hello");  // Functor usage
    printFunction("Hello");
}

// Flexible functor example
class Adder {
public:
    int operator()(int x, int y) {
        return x + y;
    }
};

void testAdder() {
    Adder adder;
    int result = adder(10, 20);
    std::cout << result << std::endl;
    
    // Anonymous functor object
    std::cout << Adder()(10, 20) << std::endl;
}

5. Inheritance

  • Benefits: Reduces code duplication.
  • Public inheritance syntax: class Derived : public Base
  • Derived class inherits common features from base class while adding specific ones.
// Base class with common interface
class BasePage {
public:
    void header() {
        std::cout << "Home, Courses, Login, Register (Common Header)" << std::endl;
    }
    void footer() {
        std::cout << "Help Center, Collaboration, Site Map (Common Footer)" << std::endl;
    }
    void sidebar() {
        std::cout << "Java, Python, C++ (Common Category List)" << std::endl;
    }
};

class PythonPage : public BasePage {
public:
    void content() {
        std::cout << "Python Course Videos" << std::endl;
    }
};

void testInheritance() {
    std::cout << "Python Download Page:" << std::endl;
    PythonPage page;
    page.header();
    page.footer();
    page.sidebar();
    page.content();
}

6. Inheritance Types

Public Inheritance

class BaseClass1 {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class Derived1 : public BaseClass1 {
public:
    void accessMembers() {
        publicMember = 10;    // Public in derived class
        protectedMember = 20; // Protected in derived class
        // privateMember = 10; // Error: inaccessible
    }
};

void testPublicInheritance() {
    Derived1 obj;
    obj.publicMember = 10;
    // obj.protectedMember = 10; // Error: protected
    // obj.privateMember = 10;   // Error: private
}

Protected Inheritance

class BaseClass2 {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class Derived2 : protected BaseClass2 {
public:
    void accessMembers() {
        publicMember = 100;   // Becomes protected in derived class
        protectedMember = 100; // Remains protected
        // privateMember = 100; // Error: inaccessible
    }
};

void testProtectedInheritance() {
    Derived2 obj;
    // obj.publicMember = 100;   // Error: protected
    // obj.protectedMember = 100; // Error: protected
    // obj.privateMember = 100;   // Error: private
}

Private Inheritance

class BaseClass3 {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class Derived3 : private BaseClass3 {
public:
    void accessMembers() {
        publicMember = 100;   // Becomes private in derived class
        protectedMember = 100; // Becomes private
        // privateMember = 100; // Error: inaccessible
    }
};

void testPrivateInheritance() {
    Derived3 obj;
    // obj.publicMember = 100;   // Error: private
    // obj.protectedMember = 100; // Error: private
    // obj.privateMember = 100;   // Error: private
}

7. Object Model in Inheritance

Use developer command prompt tools to inspect object models:

  • Change drive: F:
  • Navigate path: cd path
  • View layout: cl /d1 reportSingleClassLayoutClassName filename
// Object model in inheritance
class BaseClass {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class DerivedClass : public BaseClass {
public:
    int derivedMember;
};

void testObjectModel() {
    DerivedClass obj;
    // All non-static members from base class are inherited
    // Private members are hidden by compiler but still inherited
    std::cout << sizeof(obj) << std::endl; // Output: 16
}
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.