0% found this document useful (0 votes)
5 views

Functions in C++

Functions in C++

Uploaded by

keerthana.m2021
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

Functions in C++

Functions in C++

Uploaded by

keerthana.m2021
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 20

Functions in C++

Functions in C++ are blocks of code designed to perform a specific task. They help break
down complex problems into simpler pieces, improving code readability, reusability, and
maintainability.

1. Inline Functions

An inline function is a function in which the compiler attempts to expand the code in place
where the function call is made, instead of jumping to the function's body. This can improve
performance by avoiding function call overhead for small, frequently used functions.
However, large functions may not be inlined by the compiler.

Syntax:

cpp

inline int add(int a, int b) {


return a + b;
}

Example:

cpp

inline int square(int x) {


return x * x;
}

int main() {
int result = square(5); // No function call overhead, the expression
is expanded in place
return 0;
}

2. Call by Value

In call by value, a copy of the actual arguments is passed to the function, and any
modifications made to the parameters within the function do not affect the original values.

Example:

cpp

void increment(int x) {
x = x + 1; // This modifies only the copy of 'x'
}

int main() {
int num = 10;
increment(num); // num remains 10
return 0;
}
3. Call by Reference

In call by reference, the actual arguments are passed to the function using references or
pointers. Changes made to the parameters will reflect in the original arguments.

Example:

cpp

void increment(int &x) {


x = x + 1; // This modifies the actual 'x'
}

int main() {
int num = 10;
increment(num); // num becomes 11
return 0;
}

4. Function Overloading

Function overloading allows you to define multiple functions with the same name but
different parameter types or numbers of parameters. The correct function to call is determined
at compile-time based on the arguments passed.

Example:

cpp

int add(int a, int b) {


return a + b;
}

double add(double a, double b) {


return a + b;
}

int main() {
int result1 = add(2, 3); // Calls int version
double result2 = add(2.5, 3.5); // Calls double version
return 0;
}

Classes and Objects

1. Declaring Objects

An object is an instance of a class, and you can declare it just like a variable of basic types.
Example:

cpp
class Car {
public:
string brand;
void display() {
cout << "Car brand: " << brand << endl;
}
};

int main() {
Car myCar; // Object of class Car
myCar.brand = "Toyota";
myCar.display();
return 0;
}

2. Defining Member Functions

A member function is a function that operates on an object's data members. You can define
them inside or outside the class.

Example:

cpp

class Rectangle {
public:
int length;
int breadth;

int area() { // Member function inside class


return length * breadth;
}
};

int main() {
Rectangle rect;
rect.length = 10;
rect.breadth = 5;
cout << "Area: " << rect.area() << endl;
return 0;
}

3. Static Member Functions

A static member function belongs to the class rather than to any specific object. It can only
access static member variables.

Example:

cpp

class Employee {
public:
static int count; // Static member variable
static void displayCount() { // Static member function
cout << "Employee count: " << count << endl;
}
};

int Employee::count = 0; // Initializing static member

int main() {
Employee::displayCount(); // Accessed without an object
return 0;
}

4. Array of Objects

You can create arrays of objects in C++ just like arrays of basic types.

Example:

cpp
class Student {
public:
string name;
int grade;
void display() {
cout << "Name: " << name << ", Grade: " << grade << endl;
}
};

int main() {
Student students[3]; // Array of 3 student objects
students[0].name = "Alice";
students[0].grade = 90;
students[1].name = "Bob";
students[1].grade = 85;

for (int i = 0; i < 2; i++) {


students[i].display();
}
return 0;
}

5. Friend Function

A friend function allows access to the private and protected members of a class, even though
it is not a member of the class.

Example:

cpp
class Box {
private:
int width;
public:
Box() : width(5) {}

friend void printWidth(Box b); // Friend function declaration


};

void printWidth(Box b) {
cout << "Width: " << b.width << endl; // Can access private member
}

int main() {
Box box;
printWidth(box);
return 0;
}

6. Overloading Member Functions

Member functions can also be overloaded in a class based on the number or types of
parameters.

Example:

cpp
class Printer {
public:
void print(int i) {
cout << "Printing integer: " << i << endl;
}

void print(double d) {
cout << "Printing double: " << d << endl;
}
};

int main() {
Printer p;
p.print(5); // Calls integer version
p.print(3.14); // Calls double version
return 0;
}

Bitfields and Classes

Bitfields are used in classes to store data in a more compact form by specifying the number
of bits used for each member.

Example:

cpp
class Date {
public:
unsigned int day : 5; // 5 bits to store day (0-31)
unsigned int month : 4; // 4 bits to store month (0-15)
unsigned int year : 7; // 7 bits to store year (0-127)
};
int main() {
Date d;
d.day = 15;
d.month = 10;
d.year = 21;
cout << "Date: " << d.day << "/" << d.month << "/20" << d.year << endl;
return 0;
}

Constructor and Destructor with Static Members

Constructor

A constructor initializes an object when it is created. It can also modify static members.

Example:

cpp
class Counter {
public:
static int count;
Counter() {
count++; // Increment static member
cout << "Object created, count: " << count << endl;
}
~Counter() {
count--; // Decrement static member
cout << "Object destroyed, count: " << count << endl;
}
};

int Counter::count = 0;

int main() {
Counter c1, c2; // Count will increment with each object
return 0;
}

Destructor A destructor is called when an object goes out of scope or is explicitly deleted.
It can also modify static members.
Inheritance in C++

Inheritance is a fundamental concept in Object-Oriented Programming (OOP) that allows one


class to inherit properties (fields and methods) from another class. In C++, the class that
inherits is called the derived class, and the class from which the inheritance occurs is the
base class. This promotes code reusability and establishes a hierarchical relationship between
classes.

There are several types of inheritance in C++:

Types of Inheritance:

1. Single Inheritance:
o In single inheritance, a derived class inherits from only one base class.

Example:

cpp
class Base {
public:
int baseVar;
};

class Derived :
public Base {
public:
int derivedVar;
};

2. Multiple Inheritance:
o In multiple inheritance, a derived class inherits from more than one base class.

Example:

Cpp

class Base1 {
public:
int base1Var;
};

class Base2 {
public:
int base2Var;
};

class Derived : public Base1, public Base2 {


public:
int derivedVar;
};
3. Multilevel Inheritance:
o In multilevel inheritance, a class is derived from another class, which is also derived
from another class, forming a chain.

Example:

Cpp

class Base {
public:
int baseVar;
};

class Intermediate : public Base {


public:
int intermediateVar;
};

class Derived : public Intermediate {


public:
int derivedVar;
};

4. Hierarchical Inheritance:
o In hierarchical inheritance, multiple classes are derived from a single base class.

Example:

cpp
class Base {
public:
int baseVar;
};

class Derived1 : public Base {


public:
int derived1Var;
};

class Derived2 : public Base {


public:
int derived2Var;
};

5. Hybrid Inheritance:
o Hybrid inheritance is a combination of two or more types of inheritance. It usually
involves a mix of hierarchical and multiple inheritance.
Multipath inheritance:

class A {

public:

void show() {

cout << "Class A" << endl;

};

class B : public A {

};

class C : public A {

};

class D : public B, public C {

};

int main() {

D obj;

obj.show(); // Error: Ambiguity because both B and C inherit from A

return 0;

In this case, class D inherits from both B and C, which each inherit from A. This leads to
ambiguity because D now has two copies of the A class, one through B and one through C.

Solving Multipath Inheritance using Virtual Inheritance:


To solve the ambiguity, we use virtual inheritance, which ensures that there is only one
shared instance of the base class (A in this case), even when inherited through multiple paths.

cpp

class A {
public:
void show() {
cout << "Class A" << endl;
}
};

class B : virtual public A {


};

class C : virtual public A {


};

class D : public B, public C {


};

int main() {
D obj;
obj.show(); // No ambiguity, only one copy of A is inherited
return 0;
}

Explanation:

 By making B and C inherit from A virtually, only one instance of A is inherited by D,


thus resolving the ambiguity.
 Now, when you call obj.show(), it’s clear that there is only one show() method from
A.

Operator Overloading in C++

Operator overloading allows you to redefine how operators work with user-defined types
(such as objects of a class). C++ allows most operators to be overloaded so that they can
operate on objects in a natural way, similar to built-in data types.

Types of Operator Overloading:

1. Unary Operator Overloading:


o Unary operators operate on a single operand. These operators include ++, --, -
(negation), and ! (logical NOT).
Syntax:

return_type operator operator_name();

Example (Overloading ++):

cpp
Copy code
class Counter {
private:
int count;
public:
Counter() : count(0) {}

// Overload ++ for prefix increment


void operator++() {
++count;
}

void display() {
cout << "Count: " << count << endl;
}
};

int main() {
Counter c;
++c; // Calls overloaded ++ operator
c.display(); // Output: Count: 1
return 0;
}

2. Binary Operator Overloading:


o Binary operators take two operands and include +, -, *, /, etc.

Syntax:

return_type operator operator_name(const Type &);

Example (Overloading +):

cpp

class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}

// Overload + operator
Complex operator+(const Complex& obj) {
Complex temp;
temp.real = real + obj.real;
temp.imag = imag + obj.imag;
return temp;
}

void display() {
cout << real << " + " << imag << "i" << endl;
}
};

int main() {
Complex c1(3, 4), c2(1, 2);
Complex c3 = c1 + c2; // Calls overloaded + operator
c3.display(); // Output: 4 + 6i
return 0;
}

3. Overloading Friend Functions:


o A friend function can be used to overload operators when the left operand is not an
object of the class.

Example (Overloading << operator using a friend function):

cpp
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}

// Friend function to overload << operator


friend ostream& operator<<(ostream& out, const Complex& c);
};

// Definition of the friend function


ostream& operator<<(ostream& out, const Complex& c) {
out << c.real << " + " << c.imag << "i";
return out;
}

int main() {
Complex c1(3, 4);
cout << c1 << endl; // Calls overloaded << operator
return 0;
}

Type Conversion:

Type conversion allows converting objects from one data type to another. In C++, it can be
done in the following ways:

1. Basic Type to Class Type:


o You can convert a basic type (such as int, float, etc.) into a class object using a
constructor.

Example:

class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
// Constructor for basic to class type conversion
Complex(int realPart) {
real = realPart;
imag = 0;
}
};

int main() {
Complex c;
c = 5; // Integer to Complex conversion
return 0;
}

2. Class Type to Basic Type:


o You can convert a class object into a basic type by overloading the operator
keyword.

Example:

cpp
Copy code
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i = 0) : real(r), imag(i) {}

// Overload type conversion operator to int


operator int() {
return real;
}
};

int main() {
Complex c(5, 3);
int realPart = c; // Class to int conversion
cout << realPart << endl; // Output: 5
return 0;
}

3. Class Type to Class Type:


o You can convert one class object into another by overloading the type conversion
operator or by using a constructor.

Constructor and Destructor with Static Members

 Constructor: A constructor is a special member function that initializes objects of a


class. It is automatically called when an object is created.

Syntax:

cpp
Copy code
class ClassName {
public:
ClassName() {
// Constructor code
}
};

 Destructor: A destructor is a special member function that is called when an object is


destroyed. It is used to release resources allocated by the object.

Syntax:

cpp
Copy code
class ClassName {
public:
~ClassName() {
// Destructor code
}
};

 Static Members: Static data members are shared by all objects of a class, and static
member functions can access static data members.

Example:

cpp
Copy code
#include<iostream>
using namespace std;

class Test {
public:
static int count; // Static data member

// Constructor
Test() {
count++;
}

// Destructor
~Test() {
count--;
}

// Static function to display count


static void showCount() {
cout << "Object count: " << count << endl;
}
};

int Test::count = 0; // Initialization of static data member

int main() {
Test t1, t2;
Test::showCount(); // Output: Object count: 2

return 0;
}

These topics together form a comprehensive introduction to inheritance, operator


overloading, type conversion, and object-oriented features in C++. They are essential for
building complex, maintainable software systems in C++.

4o

You said:
virtual base classes - abstract classes

ChatGPT said:
ChatGPT

Virtual Base Classes in C++

In C++, virtual base classes are used to prevent multiple copies of a base class appearing in
the inheritance hierarchy when using multiple inheritance. This commonly occurs in
diamond problem scenarios, where a base class is inherited more than once in the hierarchy,
causing ambiguity and redundancy.

The Diamond Problem:

When two derived classes inherit from the same base class, and another class further derives
from these two derived classes, the base class members are duplicated. Virtual inheritance
solves this issue.

Example of the Diamond Problem (without virtual inheritance):

cpp
class Base {
public:
int data;
};

class Derived1 : public Base {


};

class Derived2 : public Base {


};

class Derived3 : public Derived1, public Derived2 {


};

int main() {
Derived3 obj;
obj.data = 5; // Error: ambiguity because both Derived1 and Derived2
have a copy of Base's data member
return 0;
}

The ambiguity arises because Derived3 has two copies of the Base class through Derived1
and Derived2.
Solution Using Virtual Base Classes:

To solve this problem, we can make Base a virtual base class in Derived1 and Derived2.

cpp
class Base {
public:
int data;
};

class Derived1 : virtual public Base {


};

class Derived2 : virtual public Base {


};

class Derived3 : public Derived1, public Derived2 {


};

int main() {
Derived3 obj;
obj.data = 5; // No ambiguity, now only one copy of Base is inherited
return 0;
}

By declaring Base as a virtual base class, Derived3 only gets one copy of Base's members,
resolving the ambiguity and preventing redundancy.

Abstract Classes in C++

An abstract class in C++ is a class that contains at least one pure virtual function. A pure
virtual function is a function that is declared but not defined in the base class and must be
overridden by derived classes.

Abstract classes cannot be instantiated on their own. They are primarily used to define an
interface or provide a base structure for derived classes, enforcing them to implement specific
functionality.

Syntax of Pure Virtual Function:

virtual return_type function_name() = 0;

Example of Abstract Class:

class Shape {
public:
// Pure virtual function (makes this class abstract)
virtual void draw() = 0;

// Non-pure virtual function (optional to override)


void info() {
cout << "This is a shape." << endl;
}
};

class Circle : public Shape {


public:
// Overriding the pure virtual function
void draw() override {
cout << "Drawing a Circle." << endl;
}
};

class Rectangle : public Shape {


public:
// Overriding the pure virtual function
void draw() override {
cout << "Drawing a Rectangle." << endl;
}
};

int main() {
Shape* shape1 = new Circle();
Shape* shape2 = new Rectangle();

shape1->draw(); // Output: Drawing a Circle.


shape2->draw(); // Output: Drawing a Rectangle.

delete shape1;
delete shape2;

return 0;
}

Explanation:

 Shape is an abstract class because it contains a pure virtual function draw().


 Derived classes (Circle and Rectangle) must provide an implementation for the draw()
function.
 An object of Shape cannot be created directly, but we can create pointers or references to it
that point to objects of derived classes.

Key Points:

 Virtual Base Classes prevent multiple copies of a base class in the inheritance hierarchy,
resolving the diamond problem.
 Abstract Classes serve as a blueprint for other classes. They enforce that certain methods
(pure virtual functions) must be implemented in derived classes, providing a framework for
future class designs.

By using virtual base classes and abstract classes, C++ promotes better code design,
reusability, and clarity in complex object-oriented systems.

Explanation of Virtual Base Classes and Abstract Classes

1. Virtual Base Classes


In C++, virtual base classes are used in multiple inheritance scenarios to solve the
diamond problem. The diamond problem occurs when a base class is inherited by two or
more classes, and then those classes are inherited by another class. Without virtual
inheritance, this can lead to multiple copies of the base class members, creating ambiguity.

The Diamond Problem (without virtual inheritance):

markdown
Copy code
Base
/ \
Derived1 Derived2
\ /
Derived3

Here, Derived3 inherits from both Derived1 and Derived2, but Derived1 and Derived2
both inherit from Base. This causes two copies of Base to be present in Derived3. When you
try to access a member of Base in Derived3, the compiler gets confused because it doesn't
know which copy to use, creating ambiguity.

Solution: Virtual Inheritance


By declaring Base as a virtual base class, you ensure that only one copy of Base is shared by
Derived1, Derived2, and subsequently by Derived3.

Example (solving the diamond problem):

cpp
Copy code
class Base {
public:
int data;
};

class Derived1 : virtual public Base {


};

class Derived2 : virtual public Base {


};

class Derived3 : public Derived1, public Derived2 {


};

int main() {
Derived3 obj;
obj.data = 10; // No ambiguity, one shared instance of Base
return 0;
}

 Without virtual inheritance, Derived3 would have two data members, one from
Derived1 and one from Derived2.
 With virtual inheritance, Derived3 shares a single copy of Base, avoiding duplication and
ambiguity.
2. Abstract Classes

An abstract class in C++ is a class that contains one or more pure virtual functions. A pure
virtual function is a function that is declared but not defined in the abstract class and must be
implemented by derived classes.

Purpose of Abstract Classes:

 Enforce an interface: They force derived classes to implement specific methods. This is
useful when you want to create a generalized blueprint (e.g., a Shape class), where each
derived class (e.g., Circle, Rectangle) must provide its own implementation of certain
functions.
 Polymorphism: Abstract classes enable runtime polymorphism, allowing different types of
objects to be treated uniformly.

Pure Virtual Function: A pure virtual function is declared in an abstract class using the
syntax:

cpp
Copy code
virtual void function_name() = 0;

The = 0 syntax means that the function has no definition in the base class and must be
overridden by derived classes.

Example of an abstract class:

cpp
Copy code
class Shape {
public:
// Pure virtual function, making this an abstract class
virtual void draw() = 0;

// Concrete function (optional for derived classes to override)


void info() {
cout << "This is a shape." << endl;
}
};

class Circle : public Shape {


public:
// Overriding the pure virtual function
void draw() override {
cout << "Drawing a Circle." << endl;
}
};

class Rectangle : public Shape {


public:
// Overriding the pure virtual function
void draw() override {
cout << "Drawing a Rectangle." << endl;
}
};
int main() {
Shape* shape1 = new Circle();
Shape* shape2 = new Rectangle();

shape1->draw(); // Output: Drawing a Circle.


shape2->draw(); // Output: Drawing a Rectangle.

delete shape1;
delete shape2;
return 0;
}

Explanation:

 Shape is an abstract class because it contains a pure virtual function draw(). You cannot
create objects of Shape directly because it lacks the definition of the draw() method.
 Circle and Rectangle are derived classes that provide their own implementation of draw(),
thus making them concrete classes.
 The use of the abstract class allows for polymorphism, where a Shape* pointer can point to
objects of different derived classes (Circle, Rectangle), and the correct draw() function
is called at runtime.

Key Points:

Virtual Base Classes:

 Used to solve the diamond problem in multiple inheritance by preventing multiple copies of
the base class.
 Ensures that only one copy of the base class is inherited by all derived classes in the
hierarchy.

Abstract Classes:

 Contain at least one pure virtual function.


 Cannot be instantiated directly; they must be inherited.
 Force derived classes to implement specific methods, ensuring consistency across derived
classes.
 Enable runtime polymorphism, allowing objects of different derived types to be treated
uniformly through a base class pointer or reference.

Together, virtual base classes and abstract classes provide powerful tools in C++ for
managing inheritance hierarchies, reducing ambiguity, and ensuring that derived classes
conform to specific behaviors or interfaces.

You might also like