Unit 4
Unit 4
UNIT 4
INTRODUCTION TO CLASSES AND INHERITANCE
• 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;
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
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
class Car {
public:
string make;
Example:
string model;
int year;
};
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)
data_type getMemberName()
{
Syntax: //Body
};
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.
string name; // Private data member // Setter function for age with validation person.setAge(30);
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
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.
Types of Constructor:
• Default constructor
• Parameterized constructor
• Copy constructor
Definition of a Constructor
class ClassName {
public:
ClassName() {
Syntax:
// Constructor code here
}
};
Default Constructor
class MyClass {
public:
MyClass() {
// Default constructor code
std::cout << "Default constructor called!" << std::endl;
Example:
}
};
• 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).
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;
}
};
• 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;
}
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:
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) {}
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;
}
public:
Rectangle(double w, double h) : width(w), height(h) {}
• 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.
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();
int main() {
// Create two Simple objects Output:
Simple obj1(10);
Simple obj2(20);
• 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.
• 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
• 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.
• 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) {}
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
• 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.
• 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
• 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.
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.
• 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
• 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.
Syntax:
class BaseClass {
// Base class members
};
• 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;
}
};
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.
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
};
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 Base {
public:
Base() { std::cout << "Base Constructor\n"; }
~Base() { std::cout << "Base Destructor\n"; } // Not virtual
};
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
};
int main() {
Base* ptr = new Derived();
delete ptr; // Both destructors are now called!
return 0;
}