Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Understanding Inheritance in C++

Tech 1

Overview

Inheritance is one of the core principles of object-oriented programming, enabling the creation of new classes based on existing ones. This mechanism allows for code reuse at the class level, making it a fundamental concept in C++.

Concept and Definition

Concept

Inheritance enables extending an existing class by inheriting its properties and behaviors. The original class is referred to as the base class or parent class, while the newly created class is known as the derived class or child class. This relationship facilitates code reusability and hierarchical design.

Definition

The syntax for defining inheritance in C++ is:

DerivedClass : AccessSpecifier BaseClass

Access specifiers define how members of the base class are accessible in the derived class:

  • public: Members remain public in the derived class.
  • protected: Members become protected in the derived class.
  • private: Members are inaccessible in the derived class.

It's recommended to explicitly specify the access specifier rather than relying on default behavior.

Assignment Between Base and Derived Objects

A derived class object can be assigned too a base class object, pointer, or reference. This operation is often described as "slicing" because only the base part of the derived object is copied.

However, assigning a base class object to a derived class object is not allowed.

Pointer and reference conversions from base to derived types are possible using casting, but they are unsafe unless the base pointer actually points to a derived object.

Example:

class Person {
protected:
    std::string name;
    std::string sex;
    int age;
};

class Student : public Person {
public:
    int studentId;
};

void Test() {
    Student student;
    
    // Assigning derived to base
    Person person = student;
    Person* ptr = &student;
    Person& ref = student;
    
    // This will cause a compilation error
    // student = person;
    
    // Safe cast if base pointer points to derived
    Student* derivedPtr = static_cast<Student*>(ptr);
}

Scope in Inheritance

Each class in an inheritance hierarchy maintains its own scope. If both the base and derived class have members with the same name, the derived class member hides the base class member. This applies even to functions, where matching function signatures trigger hiding.

Example:

class Base {
public:
    void show() { std::cout << "Base\n"; }
    int value = 1;
};

class Derived : public Base {
public:
    void show() { std::cout << "Derived\n"; }
    int value = 2;
};

int main() {
    Derived d;
    d.show(); // Calls Derived::show()
    return 0;
}

Default Member Functions in Derived Classes

When a class inherits from another, the default constructors, destructors, copy constructors, and assignment operators follow speicfic calling sequences:

  • Constructors: Derived constructor calls base constructor first.
  • Copy constructors and assignment operators: Base operations occur before derived.
  • Destructors: Derived destructor runs before base destructor.

Inheritance and Static Members

Static members of a base class are shared among all derived classes. They exist once per class hierarchy regardless of how many derived classes there are.

Friendship does not propagate through inheritance. A friend of the base class cannot access protected or private members of the derived class.

Diamond Inheritance and Virtual Inheritance

Diamond inheritance occurs when a class inherits from two or more classes that share a common base class. This leads to ambiguity and data duplication.

To resolve this, C++ uses virtual inheritance:

class A {
public:
    int data;
};

class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};

Virtual inheritance ensures that only one instance of the base class exists in the derived class, eliminating redundancy and resolving ambiguity.

Composition vs. Inheritance

Composition is generally preferred over inheritance. It represents a "has-a" relationship, where one class contains an instance of another. In contrast, inheritance represents an "is-a" relationship.

Inheritance should be used when there is a clear is-a relationship and when polymorphism is required. Otherwise, composition provides better flexibility and encapsulation.

In summary, while inheritance supports code reuse, composition offers greater design flexibility and lower coupling.

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.