Unit 2
Unit 2
UNIT 2
FUNCTIONS AND FUNCTIONS TEMPLATES
• C++ uses both function definitions and function prototypes to enable code
organization, reusability, and clarity.
Function Definition
• A function definition provides the actual implementation of a function.
• It includes the function’s name, return type, parameter list, and the body of the
function, which contains the code that is executed when the function is called.
return_type function_name(parameter_list) {
Syntax: // Function body
// Statements to be executed
}
• return_type: Specifies the type of value the function will return (e.g., int, double, void).
• function_name: The name of the function.
• parameter_list: A list of parameters (variables) passed to the function (can be empty).
• Function body: Contains the statements that define the behavior of the function.
Example
#include <iostream>
// Function definition
int add(int a, int b) {
return a + b; // Adds two integers and returns the result Output:
int main() {
int result = add(5, 3); // Function call
std::cout << "The sum is: " << result << std::endl; // Output: The sum is: 8
return 0;
}
Function Prototypes
• Function prototype: This tells the compiler what the function looks like (i.e., its
return type and parameters) but does not define the function's actual behavior.
Example
#include <iostream>
// Function prototype
int add(int, int);
// Function definition
int add(int a, int b) {
return a + b;
}
Inline Functions
• Inline function is a function which when invoked requests the compiler to replace the
calling statement with its body.
• A keyword inline is added before the function name to make it inline.
• It is an optimization technique used by the compilers as it saves time in switching between
the functions otherwise.
• Member functions of a class are inline by default even if the keyword inline is not used.
• Reduces Function Call Overhead – Eliminates the need for stack operations and jumping to a different memory
location.
• Improves Execution Speed – Faster execution for small, frequently used functions.
• Enables Compiler Optimizations – The compiler can better optimize inlined code.
• Type Safety – Unlike macros, inline functions are type-checked by the compiler.
• Better Debugging Support – Inline functions provide better debugging information compared to macros.
• Reduces Context Switching Overhead – Since there is no function call, registers don’t need to be saved and
restored.
• Useful for Template Functions – Helps avoid code duplication while maintaining efficiency.
Function-call stack and Activation Records
• The function-call stack and activation records are integral to how a program handles function
calls, manages resources, and maintains control flow.
• Function-Call Stack: The function-call stack is a runtime data structure used to store
information about active function calls in a program.
• Activation Records (Stack Frames): An activation record is the portion of the call stack
allocated for a function call. It contains everything needed to execute and return from the
function.
Key Features of the Call Stack
• Dynamic Nature:
• The stack grows when a function is called (pushing a new frame) and shrinks when the
function completes (popping the frame).
• Storage:
• Stores details about each function's execution in units called activation records or stack
frames.
• Automatic Management:
• The system automatically allocates and deallocates memory for functions during
execution.
Components of an Activation Record
• Return Address: The location in the caller function to which control returns after the
function completes.
• Saved CPU Registers: Stores the current state of registers to resume execution after the
function completes.
• Function Call: When a function is invoked, a new activation record is pushed onto
the stack.
• Function Execution: The CPU executes the function, using data in the current
activation record.
• Function Return: After the function completes, its activation record is popped, and
control returns to the caller.
Example of Call Stack
#include <iostream> How the Call Stack Works
using namespace std;
int main() {
int num1 = 5, num2 = 3; // Local variables in main
calculateProduct(num1, num2); // Call calculateProduct
return 0;
}
Default argument in Function
• In C++, default arguments allow you to provide default values for function
parameters.
• If the caller does not pass an argument for a parameter, the default value is used
instead.
• This feature helps in making functions more flexible and reduces the need for
function overloading.
Syntax:
return_type function_name(type param1 = default_value1, type param2 = default_value2, ...);
Default argument in Function
#include <iostream>
using namespace std;
int main() {
printMessage(); // Uses default argument: "Hello, World!"
printMessage("Custom msg"); // Uses provided argument: "Custom msg"
return 0;
}
Default argument in Function
#include <iostream>
using namespace std;
int main() {
display(1); // Uses default values for b and c
display(1, 5); // Uses default value for c
display(1, 5, 15); // No default values used
return 0;
}
object as function argument
In C++, you can pass objects as arguments to functions. Objects can be passed in three
ways:
• By Reference: The function works with the original object, so modifications inside
the function will affect the original.
• By Pointer: The function works with the pointer to the object, allowing
modifications to the original object.
Passing Objects by Value
• When you pass an object by value, a copy of the object is created and passed to the function. This means
that the original object is not modified by the function. This is usually less efficient if the object is large
because it involves a copy.
Output:
Passing Objects by Reference
• When an object is passed by reference, no copy of the object is made. The function works
directly with the original object, and any changes made inside the function will affect the
original object. This is generally more efficient, especially for large objects.
• You can pass by reference using the & symbol.
#include <iostream> void processObject(MyClass& obj) {
using namespace std; obj.value = 20; // Modifies the original object
obj.display(); // Displays modified value
class MyClass { }
public:
int value; int main() {
MyClass(int v) { MyClass obj(10); // Create object with value 10
value = v; processObject(obj); // Pass by reference
} obj.display(); // The original object is modified
return 0;
void display() { }
cout << "Value: " << value << endl;
}
};
Output:
Passing Objects by Pointer
• When you pass an object by pointer, you're passing the address of the object, which allows
the function to access and modify the original object. You can also check for nullptr if needed.
• You can pass by pointer using the * symbol.
#include <iostream> void processObject(MyClass* obj) {
using namespace std; if (obj != nullptr) {
obj->setValue(20); // Modifies the original object
class MyClass { obj->display(); // Displays modified value
public: }
int value; }
MyClass(int v) {
value = v; int main() {
} MyClass obj(10); // Create object with value 10
processObject(&obj); // Pass by pointer (passing address)
void display() const { obj.display(); // The original object is modified
cout << "Value: " << value << endl; return 0;
} }
void setValue(int v) {
value = v;
} Output:
};
Function returning object
• In C++, a function can return an object. This is particularly useful when implementing
functionality that generates or transforms objects.
• In C++, a friend function is a function that is not a member of a class but is allowed to access
the private and protected members of the class.
• A friend function can be a normal function, a method of another class, or even a global
function.
• The key idea is that friendship is granted by the class, not by the scope of the function.
Key points about Friend Functions
• Access to private/protected members: A friend function has access to the private and
protected members of the class, even though it is not a member itself.
• Declaration: The function is declared inside the class using the keyword friend.
• Non-member function: A friend function is not part of the class. It can be a global function
or a function in another class.
• No special return type or argument requirements: A friend function looks just like a
regular function but is given special access privileges.
Example of Friend Function
#include <iostream> // Friend function definition
using namespace std; double getLength(const Box& b) {
return b.length; // Access private member
}
class Box {
private: int main() {
Box b(10.5);
double length; // Private member
public: // Use the friend function to access private member
cout << "Length of the box: " << getLength(b) << endl;
Box(double l) : length(l) {} // Constructor to initialize length
return 0;
// Declare friend function }
Output:
Static data member and static member function
• In C++, static data members and static member functions are associated with the class itself
rather than any specific object of the class.
• This means that they are shared across all instances (objects) of the class.
• These members have specific behavior and usage rules, which are different from non-static
members.
• A static data member is a variable that is shared by all objects of the class.
• There is only one copy of the static data member, and it is common to all objects of the class.
• Static data members are useful for storing class-wide information, such as counters or
constants.
Key Characteristics:
• Shared across objects: Static data members are not tied to any specific object. All objects of the class share the
same copy of the static data member.
• Accessed using the class name: Static data members are typically accessed using the class name rather than
through an object instance.
• Defined outside the class: While a static data member is declared inside the class, it must be defined outside
the class in a source file (typically a .cpp file).
Example of static member
#include <iostream> // Static data member definition (outside the class)
int MyClass::count = 0;
• A static member function is a function that belongs to the class rather than any object of the
class.
• Since static functions do not have a this pointer, they can only access static data members or
call other static member functions.
• Static member functions cannot access non-static data members or non-static member
functions directly.
Key Characteristics:
• Does not require an object: Static member functions can be called on the class itself, not needing an instance
of the class.
• Can only access static members: Since they don’t have a this pointer, static member functions can only access
static data members or other static member functions.
• Can be called without creating an object: Static member functions are typically called using the class name.
Example of static member function
class MyClass { // Static data member definition (outside the class)
public: int MyClass::count = 0;
• In C++, a constant member function (also known as a const member function) is a member
function that guarantees not to modify the state of the object it is called on.
• It ensures that no non-const data members or non-const member functions can be modified
within that function.
• Constant member functions are used when you want to provide functionality that reads but
does not modify the object.
Syntax: returnType functionName() const;
Key Points
• Read-Only Access: Constant member functions can only read member variables, not modify them.
• Compile-Time Enforcement: If you attempt to modify any member variables in a const function, the compiler
will generate an error.
• Calling on Const Objects: A constant member function can be called on both constant and non-constant
objects. However, a non-constant member function cannot be called on a constant object.
Example of constant member function
#include <iostream> void setWidth(int w) {
width = w;
using namespace std;
}
};
Rectangle(int l, int w) : length(l), width(w) {} // Calling constant member function again after modification
cout << "New Area: " << rect.getArea() << endl; // Output: New Area: 200
• Function overloading in C++ is a feature that allows multiple functions to have the same name
but differ in the number or types of their parameters.
• The compiler differentiates between the overloaded functions based on their signature,
which includes the number of parameters, the type of parameters, and the order of
parameters.
Output:
Function Templates
• A function template is a blueprint or a generic function that can work with any data type.
• Instead of writing multiple functions for different data types, you can write a single template
function that works for all types, using the template keyword.
• This is especially useful when you want the same functionality for different data types (like
int, float, double, etc.).
template <typename T>
return_type function_name(T parameter1, T parameter2) {
Syntax:
// function body
}
Key Points
• Generic Function: A function template allows you to define a single function that can operate on different data
types.
• template Keyword: The template keyword is used to define a function template.
• Type Parameter: A placeholder (usually denoted as T, but you can choose any valid name) is used to represent
the data type.
• Automatic Type Deduction: The compiler can automatically deduce the type of the arguments when you call
the function.
Example of function Templates
#include <iostream>
using namespace std;
int main() {
// Calling template function with different types
cout << "Max of 10 and 20: " << findMax(10, 20) << endl; // int
cout << "Max of 10.5 and 7.3: " << findMax(10.5, 7.3) << endl; // double
cout << "Max of 'A' and 'Z': " << findMax('A', 'Z') << endl; // char
return 0;
}
Unary Scope Resolution Operator
• The unary scope resolution operator (::) in C++ is used to access global variables, functions, or classes when they are
hidden by local variables or classes.
• It helps in referring to global entities explicitly, even if there is a local variable or class with the same name.
Key Points:
• The scope resolution operator :: allows you to access global scope when there is a name conflict between local
and global identifiers.
• It can also be used to define methods outside the class in the global scope or to access static members of a class.
Usage:
• Accessing Global Variables or Functions: If there is a local variable with the same name as a global variable,
you can use the scope resolution operator :: to access the global variable.
• Accessing Class Members: You can use :: to define a function outside the class or to access static class
members.
Accessing Global Variable from Inside a Function
#include <iostream>
using namespace std;
int main() {
printX(); // Call the function
return 0;
}
Defining a Class Method Outside the Class
#include <iostream> // Definition of the member function using scope resolution operator
using namespace std; void MyClass::printX() {
cout << "Value of x: " << x << endl;
}
class MyClass {
int main() {
private:
MyClass obj(100);
int x; obj.printX(); // Call the printX function
return 0;
}
public:
MyClass(int val) : x(val) {}
Output:
int main() {
class MyClass { MyClass::count = 10; // Access static variable using scope
resolution
public:
MyClass::displayCount(); // Access static function using scope
static int count; // Static variable resolution
return 0;
static void displayCount() { // Static function }
cout << "Count: " << count << endl;
}
};
Output:
Introduction to Functional-Style Programming
int main() {
int result = apply_function(add, 2, 3);
cout << result << endl; // Output: 5
return 0;
}
Recursion
• Base Case: A condition that stops the recursion (prevents infinite recursion).
• Recursive Case: The part where the function calls itself with modified parameters, gradually
Advantages of Recursion:
• Simplicity: Recursive solutions often lead to simpler and more elegant code, especially for
problems like tree traversal, searching, and divide-and-conquer algorithms (like quicksort).
• Decomposing Complex Problems: Recursion helps in breaking down problems into smaller
subproblems, often making the code easier to understand.
Example of Recursion
#include <iostream>
using namespace std;
int main() {
int number = 5;
cout << "Factorial of " << number << " is " << factorial(number) <<
endl;
return 0;
}