You can write a C++ class, but what does a derived class actually receive from its base? C++ inheritance involves syntax, access transformation, five inheritance shapes, constructor order, overriding, and common compile errors. The Coding & DSA courses provide a broader learning path alongside OOP.
Inheritance in C++: the base-class and derived-class model
Inheritance constructs a new class from an existing class when the relationship is genuinely "is a". An ElectricCar object contains a Vehicle base subobject. It is not source-code copy and paste.
class ElectricCar : public Vehicle {
// ElectricCar members
};Vehicle is the base, ElectricCar is the derived class, and public is the inheritance mode. Private Vehicle data remains in the base subobject, but ElectricCar cannot access it directly.
An ElectricCar is a Vehicle, so inheritance is sensible. A Car has an Engine, so composition with an Engine data member is usually better.
C++ inheritance access modes: public, protected and private
Base member declaration | Public inheritance | Protected inheritance | Private inheritance |
|---|---|---|---|
| Stays public | Becomes protected | Becomes private |
| Stays protected | Stays protected | Becomes private |
| Never directly accessible | Never directly accessible | Never directly accessible |
Suppose Vehicle has protected int speedKmph = 60, private int registrationCode = 731, and public int getRegistrationCode() const. Inside ElectricCar::show(), reading speedKmph compiles. Reading registrationCode directly fails, while calling getRegistrationCode() returns 731. In main, car.speedKmph also fails because protected does not mean public.
Watch the default-mode trap. class ElectricCar : Vehicle means private inheritance, while struct ElectricCar : Vehicle means public inheritance. Spell out public when intended.
Types of inheritance in C++: five class shapes
Single:
Vehicle -> ElectricCar. One derived class extends one base, which suits a direct specialisation.Multilevel:
Vehicle -> ElectricCar -> AutonomousCar. Each level specialises the previous one.Hierarchical:
Vehicle -> ElectricCarandVehicle -> DieselCar. Several variants share one base interface.Multiple:
GPSDevice + MusicPlayer -> InfotainmentUnit. One class combines two independent interfaces.Hybrid or diamond:
Device -> Camera,Device -> Phone, thenCamera + Phone -> SmartUnit. It can model two roles sharing an ancestor; usevirtual public DevicewhenSmartUnitshould contain one sharedDevicebase subobject.
A permitted class graph is not automatically a good design. Keep it only when every derived object can safely act as its base.

Inheritance in C++ worked example: Vehicle to ElectricCar
This complete C++17 program uses both parts of an ElectricCar:
#include <iostream>
class Vehicle {
protected:
int speedKmph;
public:
explicit Vehicle(int speed) : speedKmph(speed) {
std::cout << "Vehicle constructor\n";
}
int distanceInHours(int hours) const {
return speedKmph * hours;
}
virtual ~Vehicle() = default;
};
class ElectricCar : public Vehicle {
private:
int batteryPercent;
public:
ElectricCar(int speed, int battery)
: Vehicle(speed), batteryPercent(battery) {
std::cout << "ElectricCar constructor\n";
}
void drive(int hours) {
int distance = distanceInHours(hours);
batteryPercent -= hours * 12;
std::cout << "Distance: " << distance << " km\n";
std::cout << "Battery: " << batteryPercent << "%\n";
}
};
int main() {
ElectricCar car(60, 80);
car.drive(2);
}The exact output is:
Vehicle constructor
ElectricCar constructor
Distance: 120 km
Battery: 56%The distance is 60 * 2 = 120 km. Battery use is 2 * 12 = 24 percentage points, leaving 80 - 24 = 56%. The run proves that the base constructor executes first, the object uses an inherited public method, and drive() operates on base and derived state.

Constructor order, overriding and virtual dispatch
Construction runs in this order: the base constructor, derived data-member initialisation, then the derived constructor body. Destruction runs in reverse. If the destructors print their names, the end-of-scope order is ElectricCar destructor followed by Vehicle destructor:
// In Vehicle
virtual ~Vehicle() { std::cout << "Vehicle destructor\n"; }
// In ElectricCar
~ElectricCar() override { std::cout << "ElectricCar destructor\n"; }Keep the base destructor virtual because a base pointer may own a derived object. Add virtual int rangeKm() const { return 300; } to Vehicle and this override to ElectricCar:
int rangeKm() const override { return batteryPercent * 4; }After the two-hour drive, Vehicle* vehicle = &car; followed by vehicle->rangeKm() returns 224, because 56 * 4 = 224. Without virtual in the base and override in the derived class, the call through the base pointer would use the base implementation and return 300.
Overriding matches a virtual base signature. Overloading reuses a name with different parameters. A derived declaration with the same name can also hide other base overloads. Write override so the compiler catches signature mistakes.
Common inheritance errors in C++ and how to fix them
Mistake | What goes wrong | Fix |
|---|---|---|
Access a base private member directly | The derived code does not compile | Use a protected operation or public accessor |
Omit | The base interface becomes private | State the inheritance mode explicitly |
Delete through a base with a non-virtual destructor | Deleting through the base pointer has undefined behaviour; derived cleanup is not guaranteed | Make the base destructor virtual |
Write | Object slicing removes the | Use a reference or pointer for polymorphism |
The diamond creates another ambiguity. If Device owns int id = 7, and both Camera : public Device and Phone : public Device are non-virtual bases of SmartUnit, the object has two Device subobjects and unit.id is ambiguous. Declare both relationships as virtual public Device; SmartUnit then has one shared Device, and unit.id resolves to 7.
Use inheritance only if every derived object can safely stand in for the base object. Otherwise prefer composition. Inheritance is not automatically faster, cleaner, or more reusable.
How exams and interviews test C++ inheritance
Practise these three trace patterns:
Bhas publicx = 3and protectedy = 4.D : protected Bexposessum()asx + y, soD().sum()returns7, butd.xis a compile error.Constructors
B(2)thenD(5)printB2 D5; destruction prints the derived part before the base part.The worked base pointer calls the overridden
rangeKm()and returns224, not300.
Try three short repairs. Build Person(name = "Riya") -> Student(roll = 42) so describe() prints Riya #42. Change class D : B to class D : public B so callers can use B's public interface. Repair the Device(id = 7) diamond with virtual inheritance so only one id exists.
These are common output-prediction, access-checking, and debugging formats. Once they feel routine, Stacks and Queues: LIFO vs FIFO, Postfix, Circular Queue is a useful next coding tutorial for applying class design to core structures.
Inheritance in C++: the short version and next step
Model a true is-a relationship.
Choose the inheritance mode deliberately.
Remember base-before-derived construction.
Use
virtualplusoverridefor runtime dispatch.Give polymorphic bases a virtual destructor.
Continue the language sequence with the C++ Programming course. If you want C, C++, Java, Python, and placement-oriented coding in one route, Coding for Placements is the broader alternative.




