KEMBAR78
Unit 4 | PDF | Class (Computer Programming) | Method (Computer Programming)
0% found this document useful (0 votes)
32 views77 pages

Unit 4

This document provides an overview of classes and inheritance in C++, detailing key concepts such as class definitions, member functions, constructors, destructors, and access specifiers. It explains the importance of encapsulation through setter and getter functions, as well as the different types of constructors including default, parameterized, and copy constructors. Additionally, it covers the scope of class members, the role of friend functions, and the principles of inheritance.

Uploaded by

remotevansh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views77 pages

Unit 4

This document provides an overview of classes and inheritance in C++, detailing key concepts such as class definitions, member functions, constructors, destructors, and access specifiers. It explains the importance of encapsulation through setter and getter functions, as well as the different types of constructors including default, parameterized, and copy constructors. Additionally, it covers the scope of class members, the role of friend functions, and the principles of inheritance.

Uploaded by

remotevansh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 77

PROGRAMMING WITH C++

UNIT 4
INTRODUCTION TO CLASSES AND INHERITANCE

Devang Patel Institute of Advance Technology and Research


Outlines
• Class and object
• Set and Get Member Functions
• Custom Constructors
• Class Scope and Accessing Class Members
• Access Functions and Utility Functions
• Destructors
• Default Assignment Operator
• Const Objects and Const Member Functions
• Composition: Objects as Members of Classes
• Friend Classes
• Aggregation
• Base Classes and Derived Classes
• Types of inheritance
• Public, private and protected in Inheritance
• Constructors and Destructors in Derived Classes
Class and object

• C++ is an object-oriented programming (OOP) language, which


means that it is built around the concept of objects and classes.
• These two are key concepts that help you organize and manage
data and behavior in a more structured way.
Class

• A class in C++ is a user-defined blueprint or template for creating


objects. It defines the properties (data members) and actions
(member functions) that its objects will have.

• A class allows you to bundle data and functions that operate on that data
together.
• The class itself is not a real entity; it’s just a definition. The object is what
holds actual values and resides in memory.
Class Syntax
class ClassName {
public:
// Data members (attributes or properties)
int attribute1;
double attribute2;

// Member functions (methods or behaviors)

Syntax: void method1() {


// Function code
}

void method2() {
// Function code
}
};
Components of a Class
• Data Members: These are the variables declared inside a class. They represent the attributes or state
of the object.

• Member Functions: Functions inside the class that define the actions an object can perform. These
can access and manipulate the data members of the class.

• Access Specifiers: Determine the visibility of members of the class. The most common ones are
• public: Members are accessible from outside the class.
• private: Members are only accessible from within the class.
• protected: Members are accessible within the class and derived classes.

• Constructor: A special member function that is called when an object is created. It is used to initialize
the object’s data members.

• Destructor: A special member function that is called when an object is destroyed (i.e., when it goes
out of scope or is explicitly deleted)
Object

• An object is an instance of a class. While a class is just a blueprint, an


object is a specific, created entity that occupies memory.
• Creating an object from a class essentially means allocating memory for it
and initializing it with default or user-specified values.

Syntax: ClassName objectName;


Example of Class and Object
#include <iostream> // Member function to display car details
using namespace std; void displayDetails() {
cout << "Car Make: " << make << endl;
cout << "Car Model: " << model << endl;
// Class definition cout << "Car Year: " << year << endl;
}
class Car { };
public:
int main() {
// Data members // Create an object of class 'Car'
string make; Car car1("Toyota", "Corolla", 2020); // Constructor is called here
string model; // Access and use the member function of the object
int year; car1.displayDetails();

return 0;
// Constructor to initialize the object }
Car(string m, string mo, int y) {
make = m;
model = mo;
year = y;
Output:
}
Core Concepts of Classes and Objects

Data Members (Attributes)


• Data members are the variables inside a class that hold information about the object.
• They represent the state of an object, and their values are specific to each object.

class Car {
public:
string make;
Example:
string model;
int year;
};
Core Concepts of Classes and Objects

Member Functions (Methods)


• Member functions are the operations or behaviors that objects of the class can perform.
• These functions can modify or access the data members.

// Member function to display car details


void displayDetails() {
cout << "Car Make: " << make << endl;
Example:
cout << "Car Model: " << model << endl;
cout << "Car Year: " << year << endl;
}
Core Concepts of Classes and Objects

Constructors and Destructors


• Constructor: A constructor is a special member function that is automatically called
when an object is created. Its main role is to initialize the object's data members.
• Default Constructor: A constructor with no parameters.
• Parameterized Constructor: A constructor that accepts parameters to initialize the object
with specific values.
class Car // Parameterized constructor
{ Car(string m, string mo, int y) {
public: make = m;
string make; model = mo;
string model; year = y;
int year; }
Example: };
// Default constructor
Car() {
make = "Unknown";
model = "Unknown";
year = 0;
}
Core Concepts of Classes and Objects

Destructor
• A destructor is called when an object is destroyed (goes out of scope). It is used for
cleaning up resources (like closing files, freeing memory) that the object may have
acquired during its lifetime.

class Car {
public:
// Constructor
Car() {
cout << "Car created!" << endl;
}
Example:
// Destructor
~Car() {
cout << "Car destroyed!" << endl;
}
};
Set and Get Member Functions

• In C++, set and get functions (also known as setter and getter functions) are commonly used
to access and modify the private data members of a class.

• These functions provide controlled access to the attributes of a class, following the principle
of encapsulation in object-oriented programming.

• By using set and get functions, we can ensure that the data is accessed in a safe and
controlled manner, and we can enforce rules or validations when setting values.
advantages of using setter and getter functions in C++

Encapsulation

• Data Hiding: Setters and getters help hide the internal implementation of a class. By
making the data members private and providing public setter and getter functions, you
can control how data is accessed and modified. This ensures that internal details are
hidden from outside code, which is a core principle of object-oriented programming.

• Control Over Data: Encapsulation provides the ability to modify or validate the data
before it’s accessed or changed, preventing direct manipulation of sensitive class
attributes.
Getter Function (Get Function)

A getter function is used to retrieve the value of a private data member. It


allows read-only access to the class attributes, meaning the external code can
access the value but cannot modify it directly.

data_type getMemberName()
{
Syntax: //Body
};

• data_type: The type of the member variable.


• getMemberName: The function name, typically following the pattern get followed by the
member variable's name.
Setter Function (Set Function)

A setter function is used to modify the value of a private data member. It allows
write access to the class attributes, and it can include validation or checks
before setting the value.

void setMemberName(data_type value)


{
Syntax: //Body
};

• data_type: The type of the member variable.


• setMemberName: The function name, typically following the pattern set followed by the
member variable's name.
Example of Get and Set
#include <iostream> int main() {

#include <string> // Getter function for age // Create a Person object

using namespace std; int getAge() const { Person person;

return age; // Return the age value

class Person { } // Set values using setter functions

private: person.setName("John Doe");

string name; // Private data member // Setter function for age with validation person.setAge(30);

int age; // Private data member void setAge(int newAge) {

if (newAge >= 0) { // Ensure the age is a positive number // Get values using getter functions

public: age = newAge; cout << "Name: " << person.getName() << endl;

// Getter function for name } else { cout << "Age: " << person.getAge() << endl;

string getName() const { cout << "Age must be a positive number!" << endl;

return name; // Return the name value } // Try to set an invalid age

} } person.setAge(-5); // This will trigger a validation message

// Setter function for name };

void setName(const string& newName) { return 0;

name = newName; // Set the name value }

Output:
Constructor

• A constructor in C++ is a special member function that is automatically called when an object
of a class is created.

• Its primary purpose is to initialize the object's data members and allocate any necessary
resources.

• Constructors are fundamental to object-oriented programming in C++ because they help


ensure that objects are in a valid and well-defined state when they are created.

Types of Constructor:
• Default constructor
• Parameterized constructor
• Copy constructor
Definition of a Constructor

A constructor has the following key properties:


• Same name as the class: The constructor's name is always identical to the class name.
• No return type: A constructor does not return any value, not even void.
• Automatically called: It is invoked automatically when an object is instantiated.
• Can be overloaded: You can have multiple constructors in a class with different
parameter lists (constructor overloading).

class ClassName {
public:
ClassName() {
Syntax:
// Constructor code here
}
};
Default Constructor

• A default constructor is one that takes no arguments. If you don't explicitly


define any constructor, C++ provides a default constructor automatically.

class MyClass {
public:
MyClass() {
// Default constructor code
std::cout << "Default constructor called!" << std::endl;
Example:
}
};

//When Create an Object


MyClass obj; // Calls the default constructor
Parameterized Constructor

• A parameterized constructor is a constructor that takes one or more


parameters. It allows you to initialize an object with specific values when it is
created.
class MyClass {
private:
int value;
public:
MyClass(int v) { // Constructor with parameter
value = v;
}

Example: void showValue() {


std::cout << "Value: " << value << std::endl;
}
};

//When create an object


MyClass obj(10); // Calls parameterized constructor with '10'
obj.showValue(); // Output: Value: 10
Copy Constructor

• A copy constructor is a special constructor used to create a new object as a


copy of an existing object.

• C++ provides a default copy constructor if you do not define one, but it
performs a shallow copy (just copying the values of data members).

Syntax: ClassName(const ClassName& other);


Example of Copy Constructor

class MyClass {
public:
int x;
MyClass(int val) : x(val) {}

// Copy constructor
MyClass(const MyClass& other) {
x = other.x;
}
Example:
void display() {
std::cout << "x = " << x << std::endl;
}
};

MyClass obj1(5);
MyClass obj2 = obj1; // Calls the copy constructor
obj2.display(); // Output: x = 5
Constructor Overloading

• In C++, you can overload constructors, meaning you can have multiple constructors with the
same name but different parameter lists. The correct constructor is selected based on the
arguments passed when the object is created.

class MyClass {
public:
MyClass() {
std::cout << "Default constructor" << std::endl;
}

MyClass(int x) {
std::cout << "Parameterized constructor with value " << x << std::endl;
}
Example:
MyClass(double x) {
std::cout << "Parameterized constructor with value " << x << std::endl;
}
};

//When an object create


MyClass obj1; // Calls default constructor
MyClass obj2(10); // Calls parameterized constructor (int)
MyClass obj3(10.5); // Calls parameterized constructor (double)
Class Scope and Accessing Class Members

• In C++, class scope refers to the context in which the members (variables and methods) of a
class are defined.
• It determines how and where these members can be accessed, modified, or used.
• The accessibility of class members is governed by access specifiers (public, private, and
protected).

Access Specifiers:
• public: Members declared as public can be accessed from anywhere (outside the class as well as inside).
• private: Members declared as private can only be accessed from within the class itself or by its friend functions.
• protected: Members declared as protected can be accessed within the class and by classes that inherit from it.
Class Definition and Scope
• In C++, a class is defined using the class keyword, and it has a scope that defines its members
(variables and functions).
• All members inside a class are defined in that scope, and you can access them using objects of
the class, or, in some cases, directly within the class itself.
class MyClass {
public: // public section
int publicVar; // can be accessed outside the class
void publicMethod() {
// Can be called from outside the class
std::cout << "Public Method" << std::endl;
}

Example: private: // private section


int privateVar; // can only be accessed within the class
void privateMethod() {
std::cout << "Private Method" << std::endl;
}

protected: // protected section


int protectedVar; // can be accessed by derived classes
};
Example of Accessing Class public Members

class MyClass {
public:
int publicVar; // Public member
void publicMethod() {
std::cout << "Public Method" << std::endl;
}
};
Example:
int main() {
MyClass obj;
obj.publicVar = 10; // Accessible because it's public
obj.publicMethod(); // Accessible because it's public
return 0;
}
Example of Accessing Class Private Members
Example:

class MyClass { int main() {


private: MyClass obj;
int privateVar; // Private member // obj.privateVar = 10; // Error: privateVar is private
void privateMethod() { obj.setPrivateVar(10); // Accessing private variable through public setter
std::cout << "Private Method" << std::endl; obj.getPrivateVar(); // Accessing private variable through public getter
} return 0;
}
public:
void setPrivateVar(int value) { // A public setter
privateVar = value;
}
void getPrivateVar() {
std::cout << "Private Variable: " << privateVar << std::endl;
}
};
Example of Accessing Class Protected Members
class Base {
protected:
int protectedVar;
};

class Derived : public Base {


public:
void accessProtectedVar() {
protectedVar = 5; // Can access protected member in derived class
Example: std::cout << "Protected Variable: " << protectedVar << std::endl;
}
};

int main() {
Derived obj;
obj.accessProtectedVar(); // Access protected member via derived class
return 0;
}
Friend Functions (Accessing Private Members)
• Friend functions allow specific non-member functions to access private and protected
members of the class.

• This is useful when you need to access private members but don’t want to expose them to the
outside world. class MyClass {
private:
int privateVar;

public:
MyClass(int val) : privateVar(val) {}

friend void friendFunction(MyClass &obj); // Declare friend function


};

Example: void friendFunction(MyClass &obj) {


// Access private member directly from friend function
std::cout << "Private Var: " << obj.privateVar << std::endl;
}

int main() {
MyClass obj(10);
friendFunction(obj); // Friend function can access private member
return 0;
}
Access Functions and Utility Functions

• In C++, access functions and utility functions are often used to interact with data members
of a class or perform common tasks.

• Access Functions
• Access functions, also known as getter and setter functions, are used to read (get) or modify (set) the private or protected members of a
class. Since C++ supports the concept of encapsulation, which keeps data members private to prevent direct access from outside the class,
access functions provide a controlled way of accessing and modifying that data.
• Types of Access Functions:
• Getter (Accessors): These functions return the value of private data members.
• Setter (Mutators): These functions set the value of private data members.

• Utility Functions
• Utility functions are helper functions that provide common tasks or operations that assist with class
functionality but are not necessarily related to direct access to data members. These functions are
typically used to simplify complex operations, improve readability, or offer convenience.
• Utility functions can be:
• Functions that perform calculations or transformations.
• Functions that validate conditions.
• Functions that manage resources, etc.
Example of Access Function
class Person {
private:
std::string name;
int age;

public:
// Getter (Access function)
std::string getName() const {
return name;
}

// Setter (Access function)


void setName(const std::string& newName) {
name = newName;
Example: }

// Getter (Access function)


int getAge() const {
return age;
}

// Setter (Access function)


void setAge(int newAge) {
if (newAge >= 0) { // Simple validation
age = newAge;
}
}
};
Example of Utility Function
class Rectangle {
private:
double width, height;

public:
Rectangle(double w, double h) : width(w), height(h) {}

// Utility function: Calculate area


double calculateArea() const {
return width * height;
}
Example:
// Utility function: Calculate perimeter
double calculatePerimeter() const {
return 2 * (width + height);
}

// Utility function: Check if square


bool isSquare() const {
return width == height;
}
};
Destructors

• A destructor is a special member function in a class that is called when an object of that class
is destroyed or goes out of scope.
• The primary role of a destructor is to release any resources (such as memory or file handles)
that were acquired by the object during its lifetime.

Key Characteristics of Destructors:


• Automatic Call: A destructor is automatically called when an object goes out of scope or is explicitly deleted (in
the case of dynamically allocated memory using new).
• No Return Type: Unlike regular functions, destructors do not have a return type, not even void.
• Same Name as the Class: A destructor has the same name as the class, preceded by a tilde (~).
• Cannot Take Arguments: Destructors do not accept parameters and therefore cannot be overloaded.
• Called Once: A destructor is called only once during the lifetime of an object—when the object is destroyed.

Syntax: ~ClassName();
Example of Destructor
#include <iostream>
class MyClass {
public:
// Constructor
MyClass() {
std::cout << "Constructor called\n";
Output:
}

// Destructor
Example: ~MyClass() {
std::cout << "Destructor called\n";
}
};

int main() {
MyClass obj;
return 0;
}
Default Assignment Operator

• In C++, the assignment operator (operator=) is used to assign the contents of one object to
another object of the same type.

• If you do not explicitly define an assignment operator for a class, the compiler provides a
default assignment operator.

• This default operator performs a member-wise assignment, meaning it assigns each member
variable of one object to the corresponding member variable of another object.
Example of Default Assignment Operator
#include <iostream> cout << "obj1: "; obj1.print();
using namespace std; cout << "obj2: "; obj2.print();

class Simple { // Use default assignment operator


public: obj2 = obj1; // Default assignment operator is called here
int value;
cout << "\nAfter assignment:" << endl;
// Constructor cout << "obj1: "; obj1.print();
Simple(int v) : value(v) {} cout << "obj2: "; obj2.print();

// Print function return 0;


Example: void print() const { }
cout << "value: " << value << endl;
}
};

int main() {
// Create two Simple objects Output:
Simple obj1(10);
Simple obj2(20);

cout << "Before assignment:" << endl;


Const Objects

• A const object is an object that cannot have its state modified after it is initialized. When you
declare an object as const, you are telling the compiler that its value should not be changed.

Syntax: const MyClass obj;

• This means that obj is a constant object, and its members cannot be modified through that
object.
• If any member of MyClass is non-const, attempting to modify it will result in a compiler error.
Key Points of Const Object

• Const objects can only call const member functions.

• You can initialize a const object through its constructor, but after initialization, its members
cannot be changed.

• Const objects are typically used when you want to ensure that the object’s data remains read-
only after its creation.
Example of Const Objects

class MyClass {
public:
int value;
MyClass(int v) : value(v) {}
void setValue(int v) { value = v; }
int getValue() const { return value; }
};
Example:
int main() {
const MyClass obj(10); // const object
// obj.value = 20; // Error: Cannot modify const object
std::cout << obj.getValue(); // OK: Can call const member functions
// obj.setValue(20); // Error: Cannot call non-const function
}
Const Member Functions

• A const member function is a function that guarantees it will not modify the state of the
object. This is indicated by adding const to the function's declaration after the parameter list.

Syntax: ReturnType functionName() const;

• This tells the compiler that this member function does not modify any member variables of
the object (except for mutable members), and it can be called on const objects.
Key Points of Const Member Functions
• Const member functions can be called on const objects or const references to objects.

• A const member function can only call other const member functions within it, and cannot
modify non-mutable member variables.

• It can be used to guarantee that the method will not change the state of the object, making it
safer in multi-threaded or read-only scenarios.
Example of Const Member Function
class MyClass {
public:
int value;

MyClass(int v) : value(v) {}

// Const member function: Guarantees no modification


int getValue() const {
return value;
}

Example: // Non-const member function: Can modify object state


void setValue(int v) {
value = v;
}
};

int main() {
const MyClass obj(10); // const object
std::cout << obj.getValue(); // OK: Can call const function
// obj.setValue(20); // Error: Cannot call non-const function
}
Composition: Objects as Members of Classes

• In object-oriented programming, composition is a design principle where one class contains


objects of other classes as its members.

• This allows you to build complex types by combining simpler ones. Composition is often
described as a "has-a" relationship, where one object "has" other objects as part of its
structure.

• In C++, composition is implemented by including objects of other classes as data members in


a class.

• The lifetime of these objects is controlled by the containing (or "composite") class.
Composition is preferred over inheritance when the relationship between objects is better
described as "a part of" rather than "is a".
Composition Example

#include <iostream> public:


using namespace std; void startCar() {
engine.start(); // Start the engine as part of starting the car
class Engine { cout << "Car is now running!" << endl;
public: }
void start() {
cout << "Engine started!" << endl; void stopCar() {
} engine.stop(); // Stop the engine as part of stopping the car
cout << "Car has stopped." << endl;
void stop() { }
cout << "Engine stopped!" << endl; };
} Output:
}; int main() {
Car myCar;
class Car { myCar.startCar(); // Car starts, and engine starts
private: myCar.stopCar(); // Car stops, and engine stops
Engine engine; // Composition: Car "has" an Engine return 0;
}
Advantages of Composition

• Reusability: Components of the composed class (like Engine in the Car class) can be reused
in other contexts (e.g., a Boat might have an Engine).

• Encapsulation: It allows for better abstraction, as the internal workings of the composed
objects are hidden from the outside world.

• Flexibility: Composition provides greater flexibility compared to inheritance because you


can easily replace or change the components (objects) of the class.
Friend Classes
• A friend class in C++ is a class that has access to the private and protected members of
another class. This allows two classes to work closely together while still maintaining
encapsulation.

• Syntax of Friend Class


A class can declare another class as a friend using the friend keyword.
Example
#include <iostream> class B {
using namespace std; public:
void display(A obj) {
class B; // Forward declaration
// Accessing private member of class A
class A { cout << "Value of numA: " << obj.numA << endl;
private: }
int numA; };
public:
int main() {
A(){
numA=100; A objA;
} B objB;
objB.display(objA); // B can access private data of A
// Declaring class B as a friend return 0;
friend class B; }
};

Output:
Benefits of Friend Classes
• Allows direct access to private data – Useful for tightly coupled classes.

• Maintains Encapsulation – Only the specific class gets access, rather than making the data
public.

• Better Performance – Avoids unnecessary getter/setter functions.

• Useful for Operator Overloading – Helps in overloading operators that need access to
private data.
Aggregation
• Aggregation is a type of association that represents a "has-a" relationship
between two classes. It’s a way to create complex classes by combining
simpler ones.
• One class (the container) contains objects of another class (the contained).
• The lifetime of the contained objects is independent of the container. (If the container is
destroyed, the contained objects can still exist.)

Example:
• Let’s say we have a Department and an Employee class. A department has employees, but
employees can exist even if the department is dissolved.
Example
#include <iostream> void startCar() {
using namespace std; engine->start(); // Using Engine's functionality
cout << "Car is running!" << endl;
class Engine { }
public: };
void start() {
cout << "Engine started!" << endl; int main() {
} Engine eng; // Engine object created independently
}; Car car(&eng); // Car has an Engine

class Car { car.startCar(); // Starting the car


private:
Engine* engine; // Aggregation: Car has an Engine return 0;
public: }
Car(Engine* eng){
engine=eng;
Output:
}
Base Classes and Derived Classes
• Base Class
• A Base Class is a class that provides attributes and behaviors (methods) that can be inherited by
other classes (Derived Classes). It serves as a parent class in inheritance.

• Derived Class
• A Derived Class is a class that inherits properties and methods from a Base Class. It allows code
reuse and follows an "is-a" relationship.
Example
#include <iostream> int main() {
using namespace std; Dog myDog;
myDog.eat(); // Inherited from Animal (Base Class)
// Base class myDog.bark(); // Own function
class Animal {
public: return 0;
void eat() { }
cout << "This animal eats food." << endl;
}
};

// Derived class
class Dog : public Animal {
public:
void bark() {
Output:
cout << "The dog barks!" << endl;
}
};
Inheritance
• Inheritance is a fundamental concept in C++ that allows a Derived Class to
inherit properties and methods from a Base Class. It enables code reusability
and establishes a relationship between classes.

• Types of Inheritance in C++


• Single Inheritance – One class inherits from another.
• Multiple Inheritance – A class inherits from more than one base class.
• Multilevel Inheritance – A derived class inherits from another derived class.
• Hierarchical Inheritance – Multiple derived classes inherit from the same base class.
• Hybrid Inheritance – A combination of multiple inheritance types.
Syntax of Inheritance

Syntax:

class BaseClass {
// Base class members
};

class DerivedClass : public BaseClass {


// Derived class members
};
Single Inheritance
• Single inheritance is a type of inheritance in which a derived class
inherits from only one base class. This is the simplest form of
inheritance and is widely used to promote code reuse.

• Key Points:
• Simple Structure – The derived class inherits only from one base class.
• Code Reusability – The derived class can reuse the functionality of the base class.
• No Ambiguity – Since there’s only one base class, there's no ambiguity in method resolution.
Example
#include <iostream> int main() {
using namespace std; Dog myDog;
myDog.eat(); // Inherited from Animal
// Base class (Parent) myDog.bark(); // Defined in Dog class
class Animal {
public: return 0;
void eat() { }
cout << "This animal eats food." << endl;
}
};

// Derived class (Child)


class Dog : public Animal {
public:
void bark() {
cout << "The dog barks!" << endl; Output:
}
};
Multiple Inheritance
• Multiple inheritance is a type of inheritance where a derived class
inherits from more than one base class. This allows the derived
class to access members from multiple parent classes.

• Key Points of Multiple Inheritance:


• Code Reusability – A derived class can reuse functionalities from multiple base classes.
• Combining Features – It allows a class to combine features from different sources.
• Ambiguity Issue – If both base classes have a function with the same name, the derived class must specify which one to use
using the scope resolution operator (::).
Example
#include <iostream> // Derived class inheriting from both Animal and Bird
using namespace std; class Bat : public Animal, public Bird {
public:
// Base class 1 void sleep() {
class Animal { cout << "This bat sleeps in the day." << endl;
public: }
void eat() { };
cout << "This animal eats food." << endl;
} int main() {
}; Bat myBat;
myBat.eat(); // Inherited from Animal
// Base class 2 myBat.fly(); // Inherited from Bird
class Bird { myBat.sleep(); // Defined in Bat
public:
void fly() { return 0;
cout << "This bird can fly." << endl; }
}
};

Output:
Multilevel Inheritance
• Multilevel inheritance is a type of inheritance where a class is derived from
another derived class. This forms a chain of inheritance, where each level
passes its properties to the next.

• Key Points of Multilevel Inheritance:


• Code Reusability – Each level reuses features of its parent.
• Hierarchy Representation – It models real-world hierarchies (e.g., Animal → Mammal
→ Dog).
• Can Lead to Complexity – If inheritance is too deep, it can make the code hard to
manage.
Example
#include <iostream> void bark() {
using namespace std; cout << "The dog barks!" << endl;
}
// Base class (Grandparent) };
class Animal {
public: int main() {
void eat() { Dog myDog;
cout << "This animal eats food." << endl; myDog.eat(); // Inherited from Animal
} myDog.breathe(); // Inherited from Mammal
}; myDog.bark(); // Defined in Dog

// Derived class (Parent) return 0;


class Mammal : public Animal { }
public:
void breathe() {
cout << "This mammal breathes air." << endl;
}
};

// Derived class (Child)


class Dog : public Mammal { Output:
public:
Hierarchical Inheritance
• Hierarchical inheritance is a type of inheritance where multiple derived
classes inherit from a single base class. This allows multiple classes to share
the properties and behavior of a common base class.

• Key Points of Hierarchical Inheritance:


• Code Reusability – The base class (Animal) provides common functionality that all
derived classes (Dog, Cat) can use.
• Independent Derived Classes – Each derived class has its own specialized behavior.
• Avoids Code Duplication – Instead of writing eat() in Dog and Cat, both inherit it from
Animal.
Example
#include <iostream> // Derived class 2 (Child)
using namespace std; class Cat : public Animal {
public:
// Base class (Parent) void meow() {
class Animal { cout << "The cat meows!" << endl;
public: }
void eat() { };
cout << "This animal eats food." << endl;
} int main() {
}; Dog myDog;
myDog.eat(); // Inherited from Animal
// Derived class 1 (Child) myDog.bark(); // Defined in Dog
class Dog : public Animal {
public: Cat myCat;
void bark() { myCat.eat(); // Inherited from Animal
cout << "The dog barks!" << endl; myCat.meow(); // Defined in Cat
}
}; return 0;
}

Output:
Hybrid Inheritance
• Hybrid inheritance is a combination of two or more types of
inheritance in a single program. It can mix single, multiple,
multilevel, or hierarchical inheritance, depending on the scenario.
Example
#include <iostream>
using namespace std; // Derived class inheriting from both Student and Teacher (Multiple Inheritance)
class TeachingAssistant : public Student, public Teacher {
// Base class public:
class Person { void showTA() {
public: cout << "This person is a Teaching Assistant." << endl;
void showPerson() { }
cout << "This is a person." << endl; };
}
}; int main() {
TeachingAssistant ta;
// First derived class (Single Inheritance)
class Student : public Person { ta.showPerson(); // Inherited from Person (Hierarchical)
public: ta.showStudent(); // Inherited from Student (Multilevel)
void showStudent() { ta.showTeacher(); // Inherited from Teacher (Multiple)
cout << "This person is a student." << endl; ta.showTA(); // Own function
}
}; return 0;
}
// Second base class for Multiple Inheritance
class Teacher {
public:
void showTeacher() {
cout << "This person is a teacher." << endl; Output:
}
};
Public, private and protected in Inheritance
• In C++, the access specifiers (public, private, protected) determine
how members of the base class are inherited in the derived class.
Public Inheritance (public)
• public members remain public in the derived class.
• protected members remain protected in the derived class.
• private members are not directly accessible in the derived class.
Example
#include <iostream> };
using namespace std;
int main() {
class Base { Derived obj;
public: obj.show();
int a = 10; cout << "Accessing a: " << obj.a << endl; // ✅ Allowed (public)
protected: // cout << obj.b; // ❌ Error: b is protected
int b = 20; return 0;
private: }
int c = 30; // Not inherited
};

class Derived : public Base {


public:
void show() {
cout << "Public a: " << a << endl; // ✅ Accessible
cout << "Protected b: " << b << endl; // ✅ Accessible Output:
// cout << c; // ❌ Error: Private members are not inherited
}
Private Inheritance (private)
• public and protected members of the base class become private in
the derived class.
• private members are not inherited.
Example
#include <iostream> cout << "Accessing b: " << b << endl; // ✅ Becomes private in
using namespace std; Derived
}
class Base { };
public:
int a = 10; int main() {
protected: Derived obj;
int b = 20; obj.show();
private: // obj.a; // ❌ Error: a is now private
int c = 30; // Not inherited return 0;
}; }

class Derived : private Base {


public:
void show() {
cout << "Accessing a: " << a << endl; // ✅ Becomes private in
Derived

Output:
Private Inheritance (private)
• public and protected members of the base class become private in
the derived class.
• private members are not inherited.
Example
#include <iostream> cout << "Accessing b: " << b << endl; // ✅ Becomes
using namespace std; private in Derived
}
class Base { };
public:
int a = 10; int main() {
protected: Derived obj;
int b = 20; obj.show();
private: // obj.a; // ❌ Error: a is now private
int c = 30; // Not inherited return 0;
}; }

class Derived : private Base {


public:
void show() {
cout << "Accessing a: " << a << endl; // ✅ Becomes
private in Derived Output:
Constructors and Destructors in Derived Classes

• When a derived class is created, its constructor is responsible for initializing


both its own members and the base class members. Similarly, when an object
is destroyed, the destructor executes in the reverse order.

• Order of Execution in Inheritance


• Base class constructor runs first.
• Derived class constructor runs next.
• Derived class destructor runs first when deleting an object.
• Base class destructor runs last.
Example
#include <iostream> ~Derived() {
using namespace std; cout << "Derived class destructor called" << endl;
}
class Base { };
public:
Base() { int main() {
cout << "Base class constructor called" << endl; Derived obj; // Object creation triggers constructor chain
} return 0; // Object destruction triggers destructor chain
~Base() { }
cout << "Base class destructor called" << endl;
}
};

class Derived : public Base {


public:
Derived() { Output:
cout << "Derived class constructor called" << endl;
}
C++ Virtual Destructor
• A virtual destructor in C++ ensures that the destructor of the
derived class is called when an object is deleted through a base
class pointer. This is crucial for proper resource cleanup when
dealing with polymorphism.

• Why Use a Virtual Destructor?


• When a class has virtual functions, it is generally a good practice to define
a virtual destructor to ensure correct destruction of derived class
objects when deleting through a base class pointer.
Example Without a Virtual Destructor
(Memory Leak)
#include <iostream>

class Base {
public:
Base() { std::cout << "Base Constructor\n"; }
~Base() { std::cout << "Base Destructor\n"; } // Not virtual
};

class Derived : public Base {


public:
Derived() { std::cout << "Derived Constructor\n"; }
~Derived() { std::cout << "Derived Destructor\n"; } // Not called if deleted
via Base*
Output:
};

int main() {
Base* ptr = new Derived(); // Base pointer pointing to Derived object
delete ptr; // Only Base's destructor is called!
return 0;
}
Using a Virtual Destructor
#include <iostream>

class Base {
public:
Base() { std::cout << "Base Constructor\n"; }
virtual ~Base() { std::cout << "Base Destructor\n"; } // Virtual
destructor
};

class Derived : public Base {


public: Output:
Derived() { std::cout << "Derived Constructor\n"; }
~Derived() { std::cout << "Derived Destructor\n"; }
};

int main() {
Base* ptr = new Derived();
delete ptr; // Both destructors are now called!
return 0;
}

You might also like