Accessing Parent Class Members in C++

Accessing Parent Class Members in C++

When building object-oriented programs in C++, inheritance allows you to create new classes (derived classes) that inherit properties and behaviors from existing classes (base or parent classes). Often, a derived class needs to extend the functionality of a parent class method, rather than completely override it. This means you might want to call the parent class’s version of a function from within the derived class’s function. This tutorial explains how to do just that.

The Scope Resolution Operator

The primary way to access members (functions and variables) of a parent class from a derived class is using the scope resolution operator (::). This operator allows you to explicitly specify which class’s member you are referring to.

Here’s how it works:

class Parent {
public:
    void print() {
        std::cout << "Parent's print function\n";
    }
};

class Child : public Parent {
public:
    void print() {
        Parent::print(); // Call the parent class's print function
        std::cout << "Child's print function\n";
    }
};

int main() {
    Child c;
    c.print();
    return 0;
}

In this example:

  • Child inherits from Parent.
  • Both Parent and Child have a function called print().
  • Inside Child::print(), Parent::print() explicitly calls the print() function defined in the Parent class.
  • The output will be:
    Parent's print function
    Child's print function
    

This demonstrates that you can call the parent class’s function before, after, or even within the derived class’s implementation.

Why Use the Scope Resolution Operator?

There are several scenarios where using the scope resolution operator is crucial:

  • Extending Functionality: When you want to add functionality to an inherited function without completely replacing it, call the parent’s function to perform the original behavior.
  • Avoiding Ambiguity: If the derived class has a member with the same name as a member in the base class (method overloading or shadowing), the scope resolution operator clarifies which member you intend to use.
  • Multiple Inheritance: When a class inherits from multiple base classes, the scope resolution operator becomes essential for specifying which base class’s member you want to access. For example, if you have Base1 and Base2, you can call Base1::function() or Base2::function().

Example with Multiple Inheritance

class Left {
public:
    void foo() {
        std::cout << "Left::foo()\n";
    }
};

class Right {
public:
    void foo() {
        std::cout << "Right::foo()\n";
    }
};

class Bottom : public Left, public Right {
public:
    void foo() {
        Left::foo();
        Right::foo();
        std::cout << "Bottom::foo()\n";
    }
};

int main() {
    Bottom b;
    b.foo();
    return 0;
}

In this case, the Bottom class inherits from both Left and Right, both of which have a foo() function. The scope resolution operator (Left::foo() and Right::foo()) is used to explicitly call the foo() function from each base class. The output will be:

Left::foo()
Right::foo()
Bottom::foo()

Virtual Functions and Polymorphism

When dealing with inheritance and function overriding, it’s important to understand the concept of virtual functions. Declaring a function as virtual in the base class allows derived classes to override the function’s behavior while still allowing the base class pointer or reference to call the correct version of the function at runtime (this is known as polymorphism).

class Parent {
public:
    virtual void print() {
        std::cout << "Parent's print function\n";
    }
};

class Child : public Parent {
public:
    void print() override {
        std::cout << "Child's print function\n";
    }
};

int main() {
    Parent* ptr = new Child();
    ptr->print(); // Calls Child::print() due to the 'virtual' keyword
    delete ptr;
    return 0;
}

In this case, because Parent::print() is declared as virtual, ptr->print() will call the print() function defined in the Child class, even though ptr is a pointer to a Parent object. The override keyword is optional but good practice as it tells the compiler you intend to override a virtual function.

Considerations

  • Access Control: You can only access public and protected members of the base class from the derived class. Private members are not accessible.
  • Ambiguity: In cases of multiple inheritance, ensure that the use of the scope resolution operator is unambiguous to avoid compilation errors.

By using the scope resolution operator and understanding the concepts of virtual functions, you can effectively leverage inheritance and polymorphism in your C++ programs.

Leave a Reply

Your email address will not be published. Required fields are marked *