OOPS Notes-Module 1&2
OOPS Notes-Module 1&2
int main() {
// Main function where execution begins
greetUser();
// Function definitions
void greetUser() {
std::cout << "Hello, welcome to the C++ program!" << std::endl;
}
Now, let’s consider a simple calculator program that performs basic arithmetic operations.
#include <iostream>
void displayMenu();
float add(float a, float b);
float subtract(float a, float b);
float multiply(float a, float b);
float divide(float a, float b);
int main() {
int choice;
float num1, num2, result;
while (true) {
displayMenu();
std::cin >> choice;
std::cout << "Thank you for using the calculator!" << std::endl;
return 0;
}
void displayMenu() {
std::cout << "Simple Calculator Menu:" << std::endl;
std::cout << "1. Add" << std::endl;
std::cout << "2. Subtract" << std::endl;
std::cout << "3. Multiply" << std::endl;
std::cout << "4. Divide" << std::endl;
std::cout << "5. Exit" << std::endl;
std::cout << "Enter your choice: ";
}
1. Include Directives: #include <iostream> allows us to use input and output streams.
2. Function Prototypes: We declare functions that we will define later. This helps in
organizing our code.
3. Main Function: The program starts execution from the main() function. It contains a
loop to display a menu and process user input.
4. Switch Statement: This handles the user’s choice and calls the appropriate arithmetic
function.
5. Functions for Operations: Each operation (add, subtract, multiply, divide) is
encapsulated in its own function, promoting code reusability.
bash
Copy code
g++ calculator.cpp -o calculator
bash
Copy code
./calculator
This simple calculator program showcases fundamental C++ concepts, such as input/output,
functions, control structures, and loops.
Classes and objects are fundamental concepts in C++. A class is a blueprint for creating objects
(instances), encapsulating data and functions that operate on that data.
Let's create a simple banking system where we have a BankAccount class to model a bank
account.
#include <iostream>
#include <string>
class BankAccount {
private:
std::string accountHolderName;
double balance;
public:
// Constructor
BankAccount(std::string name, double initialBalance) {
accountHolderName = name;
balance = initialBalance;
}
int main() {
// Creating an object of BankAccount
BankAccount account("Alice", 1000.0);
return 0;
}
Explanation
1. Class Definition:
o The BankAccount class encapsulates two private data members:
accountHolderName and balance.
o The class has a constructor to initialize these members.
2. Member Functions:
o deposit(double amount): Adds money to the balance if the amount is valid.
o withdraw(double amount): Deducts money from the balance if the amount is
valid and does not exceed the current balance.
o displayBalance(): Prints the account holder's name and current balance.
3. Main Function:
o An object of BankAccount is created with an initial balance.
o The program performs deposit and withdrawal operations and displays the
account balance after each operation.
bash
Copy code
g++ bank_account.cpp -o bank_account
bash
Copy code
./bank_account
Output
When you run the program, the output will look something like this:
This example demonstrates how to create and use classes and objects in C++. The BankAccount
class encapsulates data and behaviors related to bank accounts, showcasing the principles of
encapsulation and data abstraction.
In C++, class members can be categorized into three main types: data members, member
functions, and constructors/destructors. Here's a real-time example to illustrate these concepts.
Let’s create a simple library system where we have a Book class that represents books in a
library.
#include <iostream>
#include <string>
class Book {
private:
std::string title; // Data member
std::string author; // Data member
int publicationYear; // Data member
bool isAvailable; // Data member
public:
// Constructor
Book(std::string t, std::string a, int year) {
title = t;
author = a;
publicationYear = year;
isAvailable = true; // Initially, the book is available
}
int main() {
// Creating objects of Book
Book book1("The Great Gatsby", "F. Scott Fitzgerald", 1925);
Book book2("1984", "George Orwell", 1949);
return 0;
}
Explanation
1. Data Members:
o title, author, publicationYear, and isAvailable are private data members
that store information about each book.
2. Constructor:
o The constructor initializes the data members when a new Book object is created.
3. Member Functions:
o displayInfo(): Displays the details of the book, including its title, author, publication
year, and availability.
o checkOut(): Allows a user to check out the book. It updates the availability status.
o returnBook(): Allows a user to return the book and updates the availability status
accordingly.
4. Main Function:
o We create two Book objects.
o We display their information, check out one of the books, attempt to check it out again,
return it, and then check it out once more.
bash
Copy code
g++ library_system.cpp -o library_system
bash
Copy code
./library_system
Output
Title: 1984
Author: George Orwell
Publication Year: 1949
Availability: Available
Summary
This example demonstrates how to define a class with data members and member functions,
encapsulating the behavior of a book in a library system. This encapsulation helps maintain data
integrity and allows for organized code, showcasing the power of object-oriented programming
in C++.
In C++, constructors and destructors are special member functions that are automatically
called when an object is created or destroyed, respectively.
Constructors
A constructor is a member function that initializes objects of a class. It has the same name as
the class and does not have a return type.
#include <iostream>
class Rectangle {
private:
double length;
double width;
public:
// Constructor to initialize length and width
Rectangle(double l, double w) {
length = l;
width = w;
std::cout << "Rectangle created with length " << length << " and width
" << width << std::endl;
}
int main() {
Rectangle rect1(10.0, 5.0); // Constructor is called
std::cout << "Area of rect1: " << rect1.area() << std::endl;
return 0;
}
Explanation of Constructors
1. Constructor Definition:
o The constructor Rectangle(double l, double w) initializes the length and
width data members when a new Rectangle object is created.
o A message is printed to indicate that a rectangle has been created.
2. Object Creation:
o When Rectangle rect1(10.0, 5.0); is executed, the constructor is called,
initializing rect1 with specified dimensions.
Destructors
A destructor is a member function that is called automatically when an object goes out of scope
or is explicitly deleted. It has the same name as the class, prefixed by a tilde ( ~), and it also does
not have a return type.
#include <iostream>
class Rectangle {
private:
double length;
double width;
public:
// Constructor
Rectangle(double l, double w) {
length = l;
width = w;
std::cout << "Rectangle created with length " << length << " and width
" << width << std::endl;
}
// Destructor
~Rectangle() {
std::cout << "Rectangle with length " << length << " and width " <<
width << " is being destroyed" << std::endl;
}
int main() {
{
Rectangle rect1(10.0, 5.0); // Constructor is called
std::cout << "Area of rect1: " << rect1.area() << std::endl;
} // Destructor is called here as rect1 goes out of scope
{
Rectangle rect2(3.5, 2.0); // Constructor is called
std::cout << "Area of rect2: " << rect2.area() << std::endl;
} // Destructor is called here as rect2 goes out of scope
return 0;
}
Explanation of Destructors
1. Destructor Definition:
o The destructor ~Rectangle() is defined to output a message when an object is
destroyed, indicating which rectangle is being destroyed.
2. Object Destruction:
o When rect1 and rect2 go out of scope at the end of their respective blocks, the
destructor is called automatically.
bash
Copy code
./rectangle
Output
Summary
These concepts are fundamental in C++ and contribute to the effective management of resources
in object-oriented programming.
The scope resolution operator (::) in C++ is used to define or access the scope of a variable,
function, or class. It allows you to specify which class or namespace a particular identifier
belongs to, especially when there are overlapping names.
Example: Using Scope Resolution Operator
Let’s create a real-time example involving a class with both a global variable and a member
variable that share the same name.
#include <iostream>
#include <string>
// Global variable
std::string name = "Global Student";
class Student {
private:
std::string name; // Member variable
public:
// Constructor
Student(std::string n) {
name = n;
}
int main() {
Student student("Local Student");
student.displayNames();
return 0;
}
Explanation
1. Global Variable:
o We define a global variable name that holds the value "Global Student".
2. Class Definition:
o Inside the Student class, we have a private member variable name.
3. Constructor:
o The constructor initializes the member variable name with the value passed as an
argument.
4. Function displayNames():
o This function displays both the member variable (name) and the global variable
(::name).
o The :: operator is used to specify that we want to access the global name, not the
member variable.
5. Main Function:
o We create a Student object with a local name, then call the displayNames()
function to print both names.
bash
Copy code
g++ scope_resolution.cpp -o scope_resolution
bash
Copy code
./scope_resolution
Output
sql
Summary
In this example, the scope resolution operator allows us to disambiguate between the member
variable and the global variable. This is particularly useful in cases where names overlap, helping
to ensure clarity in your code. The scope resolution operator is also commonly used for:
Passing and returning objects in C++ allows for efficient manipulation of complex data
structures. This is commonly used in scenarios involving classes where we want to modify or
retrieve information about an object.
Let's create a simple example using a Point class to demonstrate passing and returning objects.
#include <iostream>
class Point {
private:
double x, y;
public:
// Constructor
Point(double xCoord, double yCoord) : x(xCoord), y(yCoord) {}
1. Data Members:
o The class has two private data members, x and y, representing coordinates.
2. Constructor:
o Initializes the coordinates when a Point object is created.
3. Display Function:
o Prints the coordinates of the point.
4. Add Function:
o Takes another Point object as a parameter (passed by reference).
o Returns a new Point object representing the sum of the two points.
Now, let’s see how to use this class in a program that demonstrates passing and returning objects.
cpp
Copy code
int main() {
Point p1(2.0, 3.0); // Create a Point object
Point p2(4.0, 5.0); // Create another Point object
return 0;
}
Explanation of main
1. Creating Points:
o We create two Point objects, p1 and p2.
3. Adding Points:
o We call the add() method on p1, passing p2 as an argument.
o The result is a new Point object, p3, which holds the sum of the coordinates.
4. Display Result:
o Finally, we display the coordinates of p3.
bash
Copy code
g++ point_example.cpp -o point_example
bash
Copy code
./point_example
Output
mathematica
Original Points:
Point(2, 3)
Point(4, 5)
Summary
Passing Objects: In this example, the add function takes a Point object as a parameter by
reference, which avoids unnecessary copying and allows for efficient manipulation of the data.
Returning Objects: The add function returns a new Point object representing the result of the
addition, demonstrating how you can construct and return complex objects in C++.
This approach can be extended to more complex data structures and is fundamental to object-
oriented programming in C++.
MODULE - II
Arrays
An array is a collection of elements of the same type, stored in contiguous memory locations.
#include <iostream>
using namespace std;
int main() {
const int numStudents = 5;
int grades[numStudents] = {85, 90, 78, 92, 88};
return 0;
}
Pointers
A pointer is a variable that holds the memory address of another variable. Pointers are powerful
for dynamic memory management and data structure manipulation.
#include <iostream>
using namespace std;
int main() {
int numStudents;
cout << "Enter number of students: ";
cin >> numStudents;
// Input grades
cout << "Enter grades: ";
for (int i = 0; i < numStudents; i++) {
cin >> grades[i];
}
// Display grades
cout << "Student Grades: ";
for (int i = 0; i < numStudents; i++) {
cout << grades[i] << " ";
}
cout << endl;
return 0;
}
References
A reference is an alias for another variable. Once a reference is initialized to a variable, it cannot
be changed to refer to another variable.
#include <iostream>
using namespace std;
int main() {
int x = 10, y = 20;
cout << "Before swapping: x = " << x << ", y = " << y << endl;
cout << "After swapping: x = " << x << ", y = " << y << endl;
return 0;
}
Summary
These concepts are widely used in various applications, from simple programs to complex
systems like databases, game engines, and real-time simulations. Understanding how to use
arrays, pointers, and references effectively is crucial for any C++ developer.
1.EXPRESSING ARRAYS AND POINTERS AND REFERENCES IN C++ WITH REAL TIME EXAMPLES
In C++, arrays, pointers, and references are fundamental concepts that enable efficient memory
management and manipulation of data structures. Let’s explore these concepts with real-time
examples.
Arrays
An array is a collection of elements of the same type, stored in contiguous memory locations.
#include <iostream>
using namespace std;
int main() {
const int numStudents = 5;
int grades[numStudents] = {85, 90, 78, 92, 88};
return 0;
}
Pointers
A pointer is a variable that holds the memory address of another variable. Pointers are powerful
for dynamic memory management and data structure manipulation.
#include <iostream>
using namespace std;
int main() {
int numStudents;
cout << "Enter number of students: ";
cin >> numStudents;
// Input grades
cout << "Enter grades: ";
for (int i = 0; i < numStudents; i++) {
cin >> grades[i];
}
// Display grades
cout << "Student Grades: ";
for (int i = 0; i < numStudents; i++) {
cout << grades[i] << " ";
}
cout << endl;
return 0;
}
References
A reference is an alias for another variable. Once a reference is initialized to a variable, it cannot
be changed to refer to another variable.
#include <iostream>
using namespace std;
int main() {
int x = 10, y = 20;
cout << "Before swapping: x = " << x << ", y = " << y << endl;
cout << "After swapping: x = " << x << ", y = " << y << endl;
return 0;
}
Summary
2. OOPS C++ ESTIMATING DYNAMIC ALLOCATION OPERATORS WITH REAL TIME EXAMPLES
In C++, dynamic memory allocation is often managed through operators like new, new[],
delete, and delete[]. Understanding how to properly use these operators is crucial for
resource management, particularly in Object-Oriented Programming (OOP). Below, I'll explain
dynamic allocation operators with real-time examples.
1. new and delete: Used for single object allocation and deallocation.
2. new[] and delete[]: Used for array allocation and deallocation.
Let’s create a class representing a simple dynamic array. This class will manage its own memory
allocation and deallocation.
DynamicArray Class
#include <iostream>
using namespace std;
class DynamicArray {
private:
int* arr; // Pointer to the array
int size; // Size of the array
public:
// Constructor
DynamicArray(int s) : size(s) {
arr = new int[size]; // Allocate memory for the array
cout << "DynamicArray of size " << size << " created." << endl;
}
// Destructor
~DynamicArray() {
delete[] arr; // Deallocate memory
cout << "DynamicArray destroyed." << endl;
}
int main() {
DynamicArray myArray(5); // Create a DynamicArray of size 5
// Set values
for (int i = 0; i < 5; i++) {
myArray.setValue(i, i * 10);
}
// Get values
cout << "Array values: ";
for (int i = 0; i < 5; i++) {
cout << myArray.getValue(i) << " ";
}
cout << endl;
return 0;
}
Explanation
You can extend this concept to manage a dynamic list of students in a classroom application.
Here’s a simple implementation.
#include <iostream>
#include <string>
using namespace std;
class Student {
public:
string name;
int age;
class StudentList {
private:
Student** students; // Pointer to a dynamic array of Student pointers
int size; // Current number of students
int capacity; // Maximum capacity
public:
StudentList(int cap) : size(0), capacity(cap) {
students = new Student*[capacity]; // Allocate array of Student
pointers
}
~StudentList() {
for (int i = 0; i < size; i++) {
delete students[i]; // Deallocate each Student object
}
delete[] students; // Deallocate the array of pointers
}
void displayStudents() {
for (int i = 0; i < size; i++) {
cout << "Student " << i + 1 << ": " << students[i]->name << ",
Age: " << students[i]->age << endl;
}
}
};
int main() {
StudentList myClass(3); // Maximum of 3 students
myClass.addStudent("Alice", 20);
myClass.addStudent("Bob", 22);
myClass.addStudent("Charlie", 19);
myClass.addStudent("David", 21); // Should show a message that the list is
full
myClass.displayStudents();
return 0;
}
Key Points
Dynamic Memory Management: Both examples illustrate how to allocate and
deallocate memory dynamically. The DynamicArray class handles its own memory,
while StudentList manages an array of Student pointers.
Destructor Usage: Properly releasing memory in the destructor prevents memory leaks,
ensuring that all allocated memory is freed when the objects are no longer needed.
Dynamic Structures: These examples show how to create flexible data structures that
can grow or shrink in size during runtime, which is essential in real-time applications
such as managing students or other variable data.
Using dynamic allocation effectively allows for greater flexibility and efficiency in resource
management, especially in OOP designs where object lifetimes may vary significantly.
3. IN OOPS C++ ESTIMATING DYNAMIC ALLOCATION OPERATORS WITH REAL TIME EXAMPLES
In C++, dynamic memory allocation is often managed through operators like new, new[],
delete, and delete[]. Understanding how to properly use these operators is crucial for
resource management, particularly in Object-Oriented Programming (OOP). Below, I'll explain
dynamic allocation operators with real-time examples.
1. new and delete: Used for single object allocation and deallocation.
2. new[] and delete[]: Used for array allocation and deallocation.
Let’s create a class representing a simple dynamic array. This class will manage its own memory
allocation and deallocation.
DynamicArray Class
#include <iostream>
using namespace std;
class DynamicArray {
private:
int* arr; // Pointer to the array
int size; // Size of the array
public:
// Constructor
DynamicArray(int s) : size(s) {
arr = new int[size]; // Allocate memory for the array
cout << "DynamicArray of size " << size << " created." << endl;
}
// Destructor
~DynamicArray() {
delete[] arr; // Deallocate memory
cout << "DynamicArray destroyed." << endl;
}
int main() {
DynamicArray myArray(5); // Create a DynamicArray of size 5
// Set values
for (int i = 0; i < 5; i++) {
myArray.setValue(i, i * 10);
}
// Get values
cout << "Array values: ";
for (int i = 0; i < 5; i++) {
cout << myArray.getValue(i) << " ";
}
cout << endl;
return 0;
}
Explanation
You can extend this concept to manage a dynamic list of students in a classroom application.
Here’s a simple implementation.
#include <iostream>
#include <string>
using namespace std;
class Student {
public:
string name;
int age;
class StudentList {
private:
Student** students; // Pointer to a dynamic array of Student pointers
int size; // Current number of students
int capacity; // Maximum capacity
public:
StudentList(int cap) : size(0), capacity(cap) {
students = new Student*[capacity]; // Allocate array of Student
pointers
}
~StudentList() {
for (int i = 0; i < size; i++) {
delete students[i]; // Deallocate each Student object
}
delete[] students; // Deallocate the array of pointers
}
void displayStudents() {
for (int i = 0; i < size; i++) {
cout << "Student " << i + 1 << ": " << students[i]->name << ",
Age: " << students[i]->age << endl;
}
}
};
int main() {
StudentList myClass(3); // Maximum of 3 students
myClass.addStudent("Alice", 20);
myClass.addStudent("Bob", 22);
myClass.addStudent("Charlie", 19);
myClass.addStudent("David", 21); // Should show a message that the list is
full
myClass.displayStudents();
return 0;
}
Key Points
Using dynamic allocation effectively allows for greater flexibility and efficiency in resource
management, especially in OOP designs where object lifetimes may vary significantly.
In C++, dynamic allocation operators (new, new[], delete, and delete[]) are essential for
managing memory in Object-Oriented Programming (OOP). Here’s a summary of these
operators along with real-time examples.
Key Concepts
Memory Management: Dynamic memory allocation allows for the creation of data structures
whose size can change during runtime, enabling more efficient resource usage.
Encapsulation: By managing memory within classes, you can hide implementation details from
users, providing a clean interface.
Real-Time Examples
#include <iostream>
using namespace std;
class DynamicArray {
private:
int* arr;
int size;
public:
DynamicArray(int s) : size(s) {
arr = new int[size]; // Allocate memory
}
~DynamicArray() {
delete[] arr; // Free memory
}
int main() {
DynamicArray myArray(5);
for (int i = 0; i < 5; i++) {
myArray.setValue(i, i * 10);
}
return 0;
}
Key Points:
#include <iostream>
#include <string>
using namespace std;
class Student {
public:
string name;
int age;
class StudentList {
private:
Student** students;
int size;
int capacity;
public:
StudentList(int cap) : size(0), capacity(cap) {
students = new Student*[capacity]; // Allocate array of Student
pointers
}
~StudentList() {
for (int i = 0; i < size; i++) {
delete students[i]; // Free each Student object
}
delete[] students; // Free the array of pointers
}
void displayStudents() {
for (int i = 0; i < size; i++) {
cout << "Student " << i + 1 << ": " << students[i]->name << ",
Age: " << students[i]->age << endl;
}
}
};
int main() {
StudentList myClass(3);
myClass.addStudent("Alice", 20);
myClass.addStudent("Bob", 22);
myClass.addStudent("Charlie", 19);
myClass.addStudent("David", 21); // Should indicate the list is full
myClass.displayStudents();
return 0;
}
Key Points:
The StudentList class dynamically allocates memory for an array of student pointers.
Each Student object is allocated memory using new, and all allocated memory is released in
the destructor.
Summary
Flexible Memory Usage: Objects can be created and destroyed as needed during runtime.
Efficient Resource Management: Proper use of new and delete prevents memory leaks.
Encapsulation in OOP: Memory management can be encapsulated within classes, providing a
clean interface for users.
Understanding these concepts and examples equips you to create efficient, flexible, and
maintainable applications using C++.
Function overloading in C++ allows you to define multiple functions with the same name but
different parameter lists (type or number of parameters). This feature is a key aspect of
polymorphism in Object-Oriented Programming (OOP), enhancing code readability and
flexibility.
Key Concepts of Function Overloading
Same Name, Different Signatures: Functions can have the same name as long as their
parameter types or counts differ.
Real-Time Examples
Let’s create a class that calculates the area of different geometric shapes. We will overload the
area function to handle different shapes.
#include <iostream>
using namespace std;
class Shape {
public:
// Function to calculate area of a rectangle
double area(double length, double width) {
return length * width;
}
int main() {
Shape shape;
cout << "Area of rectangle (5.0, 3.0): " << shape.area(5.0, 3.0) << endl;
cout << "Area of circle (2.0): " << shape.area(2.0) << endl;
cout << "Area of triangle (4.0, 5.0): " << shape.area(4.0, 5.0, true) <<
endl;
return 0;
}
Explanation
Overloaded Functions: The area function is overloaded for rectangles, circles, and triangles.
Flexibility: The same function name is used to calculate areas for different shapes, making the
code intuitive.
#include <iostream>
#include <string>
using namespace std;
class StringUtil {
public:
// Overloaded function for concatenating two strings
string concatenate(const string& str1, const string& str2) {
return str1 + str2;
}
int main() {
StringUtil util;
return 0;
}
Explanation
Versatile Functionality: The concatenate function can combine two strings, three strings, or a
string with an integer.
Improved Readability: Users can easily understand that all variations serve the purpose of
concatenating strings, despite the different parameters.
Summary
In C++, a copy constructor is a special constructor used to create a new object as a copy of an
existing object. This is crucial in Object-Oriented Programming (OOP) for managing resources,
especially when dealing with dynamic memory allocation or complex data structures.
cpp
Copy code
ClassName(const ClassName &obj);
Real-Time Examples
Let’s create a class that manages a dynamic array and uses a copy constructor to ensure a deep
copy.
#include <iostream>
using namespace std;
class DynamicArray {
private:
int* arr;
int size;
public:
// Constructor
DynamicArray(int s) : size(s) {
arr = new int[size]; // Allocate memory
for (int i = 0; i < size; i++) {
arr[i] = i; // Initialize with values
}
}
// Destructor
~DynamicArray() {
delete[] arr; // Free memory
}
int main() {
DynamicArray array1(5); // Create an object
cout << "Array 1: ";
array1.display();
return 0;
}
Explanation
Copy Constructor: When array2 is initialized with array1, the copy constructor is invoked,
creating a new array and copying the values from array1 to array2.
Deep Copy: Each object manages its own memory, so changes in one object do not affect the
other.
Let’s enhance the previous example by adding more complexity, such as a class representing a
simple Student object.
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int age;
public:
// Constructor
Student(const string& n, int a) : name(n), age(a) {}
// Copy Constructor
Student(const Student& obj) : name(obj.name), age(obj.age) {
cout << "Copy constructor for Student called." << endl;
}
int main() {
Student student1("Alice", 20);
cout << "Student 1: ";
student1.display();
return 0;
}
Explanation
Copy Constructor: The copy constructor for Student copies the name and age from the original
object. This is straightforward since std::string handles its own memory.
Functionality: This example demonstrates how to maintain the integrity of objects when
copying, ensuring that all relevant information is duplicated.
Summary
Resource Management: They ensure that objects manage their own resources correctly,
preventing memory issues.
Encapsulation: By providing a way to duplicate objects without exposing their internal
implementation details.
Polymorphism: Supporting OOP principles where objects can be copied and passed around
safely.
Understanding and correctly implementing copy constructors is crucial for creating robust and
efficient C++ applications, especially when dealing with dynamic resources.
In C++, default function arguments allow you to specify default values for parameters, which are
used if the caller does not provide those arguments. Here's a breakdown of how it works, along
with real-time examples to help illustrate the concept.
If the caller doesn't provide values for the parameters with default arguments, the default values
are used automatically.
Let’s take an example where we want to greet a user. The function takes two parameters: the
user's name and their greeting message. If the user does not provide a greeting message, it will
default to "Hello".
#include <iostream>
using namespace std;
int main() {
greetUser("Alice"); // Only name is provided, default
greeting will be used
greetUser("Bob", "Welcome"); // Both name and greeting are provided
return 0;
}
Output:
Hello, Alice!
Welcome, Bob!
In this example:
Here’s another real-time example: a function that sums two numbers. If the second number is not
provided, it defaults to 10.
#include <iostream>
using namespace std;
int main() {
cout << "Sum of 5 and 10: " << sum(5) << endl; // Second argument is
default
cout << "Sum of 5 and 20: " << sum(5, 20) << endl; // Both arguments
provided
return 0;
}
Output:
mathematica
In this case:
1. Default arguments must be specified in the function declaration (prototype), not in the
definition.
2. Once a default value is assigned for an argument, all subsequent arguments must have default
values. You can’t have non-default arguments after default ones.
void example(int a = 5, int b); // Error: b must also have a default value if
a does
In conclusion, default function arguments make your code more flexible by allowing functions to
be called with fewer arguments when default behavior is acceptable. This is particularly useful
when you want to provide optional parameters.
Function Overloading
#include <iostream>P
using namespace std;
void print(int i) {
cout << "Printing int: " << i << endl;
}
void print(double f) {
cout << "Printing double: " << f << endl;
}
void print(string s) {
cout << "Printing string: " << s << endl;
}
int main() {
print(42); // Calls the int version
print(3.14); // Calls the double version
print("Hello"); // Calls the string version
return 0;
}
Output:
Printing int: 42
Printing double: 3.14
Printing string: Hello
Here, all three print functions share the same name but have different parameter types (int,
double, string). The correct function is called based on the type of argument passed.
Ambiguity in Function Overloading
Ambiguity occurs when the compiler cannot decide which overloaded function to call, either
because multiple functions match the arguments or none match precisely.
#include <iostream>
using namespace std;
void display(int i) {
cout << "Integer: " << i << endl;
}
void display(float f) {
cout << "Float: " << f << endl;
}
int main() {
display(5.5); // Ambiguity occurs
return 0;
}
Error:
Vbnet
Fixing Ambiguity:
You can resolve this ambiguity by explicitly matching the argument type or adding an
overloaded function for double:
void display(double d) {
cout << "Double: " << d << endl;
}
int main() {
display(static_cast<float>(5.5)); // Calls the float version
return 0;
}
#include <iostream>
using namespace std;
void show(double x) {
cout << "One double: " << x << endl;
}
int main() {
show(5); // Ambiguity occurs
return 0;
}
Error:
vbnet
In this case:
The call show(5) matches both show(int x, int y = 0) and show(double x) because:
o The first function has a default argument, so show(5) is equivalent to show(5, 0).
o The second function could accept an integer by promoting it to a double.
Solution:
You can resolve this ambiguity by either explicitly calling the correct function or by removing
the default argument to make the parameter list unambiguous:
1. Avoid Type Promotions: Overloaded functions with closely related types (e.g., int,
float, double) can cause ambiguity. To avoid this, provide explicit overloaded functions
for each type or avoid overloading with types that may promote automatically.
2. Use Distinct Signatures: Ensure that the overloaded function signatures are sufficiently
distinct in terms of argument types or the number of arguments.
3. Be Cautious with Default Parameters: Default arguments combined with overloading
can lead to confusion. Make sure the function calls remain clear when using default
parameters.
Conclusion
Function overloading is a powerful tool in C++ that enables you to write cleaner, more intuitive
code by defining multiple versions of a function.
Ambiguity arises when the compiler cannot unambiguously determine which function to call,
often due to type promotion or default arguments.