Back to C++
2025-12-166 min read

C++ Shadowing Base Class Member Function

Learn C++ Shadowing Base Class Member Function step by step with clear examples and exercises.

Why This Matters

In this full guide on C++ Shadowing Base Class Member Functions, we aim to provide a deep understanding of an essential concept that can significantly impact your coding experience, especially during interviews and real-world programming scenarios. By learning about shadowing base class member functions, you will be better equipped to handle inheritance issues and create more flexible and reusable code in C++.

Why This Matters

Inheritance is a powerful tool in C++ that allows one class to acquire properties and methods from another class, known as the base or parent class. However, there may be situations where you want to override a method in the base class with a different implementation in the derived class (child class). This process is called shadowing. Understanding shadowing can help you avoid common pitfalls when working with inheritance and create more modular and efficient code.

Prerequisites

Before diving into the core concept, it's essential to have a solid grasp of the following:

  • Basic C++ syntax and control structures (e.g., loops, conditional statements)
  • Object-oriented programming concepts (e.g., classes, inheritance, polymorphism)

Core Concept

Shadowing Base Class Member Functions

In C++, when a derived class inherits from a base class and both contain member functions with the same name and signature, the derived class's function shadows or hides the base class's function. The derived class's implementation takes precedence over the base class's implementation when calling the method.

Here's an example to illustrate shadowing:

// Base class definition
class Shape {
public:
void draw() {
std::cout << "Drawing a generic shape.\n";
}
};

// Derived class definition (Rectangle)
class Rectangle : public Shape {
public:
void draw() {
// Calling the base class's draw() function using scope resolution operator
base::draw();
std::cout << "Drawing a rectangle.\n";
}
};

In this example, the draw() function is present in both the base class Shape and the derived class Rectangle. The Rectangle's implementation of draw() shadows the base class's implementation. When you create an instance of the Rectangle class and call the draw() method, it first calls the base class's implementation and then prints "Drawing a rectangle."

Accessing Base Class Member Functions in Derived Classes

To access the shadowed base class member function from within the derived class, you can use the base:: scope resolution operator. This allows you to call the base class's implementation of the shadowed function when needed.

Overriding Virtual and Non-Virtual Functions

Overriding Virtual Functions

When a virtual function in the base class is overridden in a derived class, it creates a new implementation that can be called on instances of the derived class. The correct implementation (either the base class's or the derived class's) will be called based on the object's type at runtime.

Overriding Non-Virtual Functions

Overriding a non-virtual function in a derived class does not shadow the base class's implementation; instead, it creates a new, unrelated function with the same name and signature. This means that if you call an overridden non-virtual function on an instance of the base class, the base class's implementation will be called, while calling it on an instance of the derived class will call the derived class's implementation.

Worked Example

Let's create a more complex example to showcase shadowing in action. We will have two classes: Animal and Dog. The Animal class has a virtual function called makeSound(), which is intended to be overridden by derived classes. The Dog class will override this function to output "Woof!" instead of the default animal sound.

#include <iostream>
using namespace std;

// Base class definition (Animal)
class Animal {
public:
virtual void makeSound() {
cout << "The animal makes a generic sound.\n";
}
};

// Derived class definition (Dog)
class Dog : public Animal {
public:
void makeSound() override {
cout << "Woof!\n";
}
};

int main() {
// Creating an instance of the Dog class
Dog myDog;

// Calling the makeSound() function on the Dog object
myDog.makeSound();

// Creating an instance of the Animal class (polymorphism)
Animal* animal = &myDog;
animal->makeSound();

return 0;
}

When you run this code, it will output "Woof!" twice, demonstrating how the Dog class has successfully overridden the makeSound() function from the base class Animal. The first call is made on the myDog object directly, and the second call is made through a polymorphic pointer to the Animal class.

Common Mistakes

  1. Forgetting to make the base class member function virtual: If you don't make the base class member function virtual, it cannot be overridden in derived classes, and shadowing won't occur. Instead, the base class's implementation will always be called.
  1. Not using scope resolution operator (base::) when accessing a shadowed base class member function from within the derived class: If you forget to use the scope resolution operator, the derived class's implementation will always be called, even if you intended to call the base class's implementation.
  1. Incorrectly overriding a non-virtual function in a derived class: When you override a non-virtual function in a derived class, it does not shadow the base class's implementation; instead, it creates a new, unrelated function with the same name and signature. This can lead to unexpected behavior when calling the function on instances of both the base and derived classes.
  1. Not understanding the difference between virtual and non-virtual functions: Failing to grasp the distinction between virtual and non-virtual functions can result in incorrect implementation choices, leading to bugs or inefficient code.

Practice Questions

  1. Create a simple example where a base class has a virtual draw() function, and a derived class shadows this function with its own implementation.
  2. Write a program that demonstrates how to access the shadowed base class member function from within the derived class using the scope resolution operator (base::).
  3. Explain what happens when you override a non-virtual function in a derived class and call it on an instance of the derived class.
  4. What is the difference between virtual and non-virtual functions, and why does it matter?
  5. In the given example with the Animal and Dog classes, how would you modify the code to make the base class's makeSound() function non-virtual, and what would happen if you did so?

FAQ

  1. What is the purpose of shadowing base class member functions in C++?
  • Shadowing allows derived classes to override the implementation of a method from the base class, providing more flexibility and customization in object-oriented programming.
  1. How can I access a shadowed base class member function from within the derived class in C++?
  • You can use the base:: scope resolution operator to call the base class's implementation of the shadowed function.
  1. What happens if I forget to make a base class member function virtual before overriding it in a derived class?
  • If you don't make the base class member function virtual, it cannot be overridden in derived classes, and shadowing won't occur. Instead, the base class's implementation will always be called.
  1. What is the difference between virtual and non-virtual functions in C++?
  • Virtual functions allow for polymorphic behavior, meaning they can have different implementations in derived classes based on the object's type at runtime. Non-virtual functions do not exhibit this behavior; their implementation remains the same across all instances of a class hierarchy.
  1. How would you modify the code to make the base class's makeSound() function non-virtual, and what would happen if you did so?
  • To make the base class's makeSound() function non-virtual, simply remove the virtual keyword from its definition in the Animal class. If you do this, the Dog class will not be able to override the function, and the base class's implementation will always be called, regardless of whether you are working with a Dog object or an Animal object. This can lead to unexpected behavior if you intended for the Dog class to have its own unique implementation of the makeSound() function.
C++ Shadowing Base Class Member Function | C++ | XQA Learn