C++ Call Base Class Method

Abdul Mateen Oct 12, 2023
  1. Inheritance in C++
  2. Issues in Calling Base Class Method
C++ Call Base Class Method

This tutorial will discuss calling the parent class method from a child class using C++. First, we will quickly refresh inheritance.

Later, we will discuss calling base class methods in different scenarios and related issues.

Inheritance in C++

Inheritance is a powerful feature of object-oriented programming. Through inheritance, child classes can share attributes and functions of the parent class, facilitating reusability in OOP.

In inheritance, two classes come into a relation known as Parent-Child, Base-Derived, or Generalized-Specialized relationship; however, base-derived jargon is most commonly adopted instead of parent and child.

Syntax of inheritance in C++:

class Parent {
  ..
};
class Child : InheritanceSpecifier Parent {
  ...
};

To create a derived class, we have to write InheritanceSpecifier followed by the name of the base class. Here, the InheritanceSpecifier can be public, private, or protected.

Moreover, the inheritance can be multiple if the names of multiple parent classes are specified while inheriting. More about kinds of inheritance can be found here.

We will use public inheritance throughout the article to keep things simple. We can call base class methods (if not private) within the child class and with the object of the child class, as demonstrated in the code below.

class P {
 public:
  void pf() { cout << "Parent class function\n"; }
};
class C : public P {
 public:
  void cf() {
    pf();
    cout << "Child class function\n";
  }
};
int main() {
  C cObj;
  cObj.cf();
  cObj.pf();
  return 0;
}

We created a parent class, P, which is publicly inherited from the child class C. The cf() function in child class C calls the base method pf().

Similarly, in the driver code (i.e., main()), the child object cObj calls the base class method directly.

Output:

Parent class function
Child class function
Parent class function

The above example was very trivial to understand the calling of base class function: within child class and with the object of the child class.

However, more complex situations may require additional caution while calling the base methods, as discussed in the following passages.

Issues in Calling Base Class Method

There seems to be no issue calling the base class method in the previous code and output. However, some related problems arise, like if the parent and child classes have the same function or child has two or more parents having the same function.

Let’s discuss these issues one by one.

Parent and Child Have the Same Function

Parent and child classes may have the same functions, and in some cases, we may want to call the parent class function with the child class object, or we may want to call the parent class function within the child class.

First, let’s see the code demonstrating the scenario.

class Parent {
 public:
  void f() { cout << "Parent class function\n"; }
};
class Child : public Parent {
 public:
  void f() { cout << "Child class function\n"; }
};
int main() {
  Child cObj;
  cObj.f();
  return 0;
}

Output:

Child class function

Here, note that the child class object calls the f() function of the child class (not from the parent). To call the f() of the parent through the child class object, we must use the parent class name with the scope resolution operator (::), as demonstrated in the following code.

class Parent {
 public:
  void f() { cout << "Parent class function\n"; }
};
class Child : public Parent {
 public:
  void f() { cout << "Child class function\n"; }
};
int main() {
  Child cObj;
  cObj.Parent::f();  // calling f() of parent class
  cObj.f();
  return 0;
}

Output:

Parent class function
Child class function

See the second line in the main() function where we have used the parent class name with the scope resolution operator. Correspondingly, in the first line of the output, we can see the message printed by f() of the parent class.

The exact syntax should be followed to call the base class function within a child class, as depicted by the code below.

class Parent {
 public:
  void f() { cout << "Parent class function\n"; }
};
class Child : public Parent {
 public:
  void f() {
    Parent::f();
    cout << "Child class function\n";
  }
};
int main() {
  Child cObj;
  cObj.f();
  return 0;
}

Output:

Parent class function
Child class function

Multiple Inheritance Ambiguity

The second issue with calling the base class method is that multiple (two or more) class parents can have the same method. In this case, the compiler confuses selecting a particular base class to call the method because the same method exists in multiple base classes.

Let’s look at a code that will generate compile-time ambiguity for the compiler while selecting a particular base class for calling the base method.

class P1 {
 public:
  void fun() { cout << "Fun from P1\n"; }
};
class P2 {
 public:
  void fun() { cout << "Fun from P2\n"; }
};
class C : public P1, public P2 {};
int main() {
  C objC;
  objC.fun();
  return 0;
}

Here, class C is inherited from two base classes (i.e., P1 and P2) and both the parents have a fun() method with the same signature.

Now, when the driver code calls the fun() function by the child object (objC), it confuses the compiler in selecting the right base class.

Let’s look into the compiler message.

base_class_3.cpp: In function int main():
base_class_3.cpp:16:7: error: request for member fun is ambiguous
  objC.fun();

The message is clearly showing that the compiler is confused. Again, the solution is the same that is use the class name with the scope resolution operator.

See the code and the related output.

class P1 {
 public:
  void fun() { cout << "Fun from P1\n"; }
};
class P2 {
 public:
  void fun() { cout << "Fun from P2\n"; }
};
class C : public P1, public P2 {};
int main() {
  C objC;
  objC.P1::fun();
  objC.P2::fun();
  return 0;
}

Output:

Fun from P1
Fun from P2

See lines 2 and 3 in the main(), where P1 and P2 class names are used with the scope resolution operator. Consequently, in the output, you can see output from both the base functions.

Related Article - C++ Inheritance