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

10VirtualFunctionsUnitV

Uploaded by

nanigir651
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)
18 views

10VirtualFunctionsUnitV

Uploaded by

nanigir651
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/ 26

SHRI SHANKARACHARYA TECHNICAL CAMPUS

Virtual Functions & Polymorphism in C++


Polymorphism is a core concept of object-oriented programming, and virtual functions play
a crucial role in achieving polymorphism in C++. It enables dynamic binding, allowing the
correct function to be called based on the actual type of the object at runtime, rather than the
type of the pointer or reference used to access the object. This provides the flexibility of
writing more generic and reusable code.
Key Concepts
1. Virtual Functions: A function in a base class declared with the virtual keyword. This
allows the derived class to override it, and the correct function is called based on the
actual object type at runtime (dynamic binding).
2. Pure Virtual Functions: A virtual function that has no implementation in the base
class and is set to 0 (virtual void function() = 0). A class with at least one pure virtual
function is abstract, meaning you cannot instantiate it directly. Derived classes must
implement these functions.
3. Dynamic Binding: The mechanism by which C++ decides at runtime which function
to invoke based on the type of the object being referred to, rather than the type of the
pointer/reference.

Virtual Functions for Late Binding (Dynamic Polymorphism)


we demonstrate the basic use of virtual functions and how dynamic polymorphism works.
Here, the sound() function in the base class Animal is virtual, so it can be overridden by
derived classes such as Dog and Cat.
#include <iostream>
using namespace std;

class Animal {
public:
virtual void sound() { // Virtual function in base class
cout << "Animal sound" << endl;
}
};

class Dog : public Animal {


public:
void sound() override { // Override the base class function
SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 1
SHRI SHANKARACHARYA TECHNICAL CAMPUS

cout << "Barking" << endl;


}
};

class Cat : public Animal {


public:
void sound() override { // Override the base class function
cout << "Meowing" << endl;
}
};

int main() {
Animal* animalPtr;
Dog dog;
Cat cat;

animalPtr = &dog;
animalPtr->sound(); // Will call Dog's sound() due to late binding

animalPtr = &cat;
animalPtr->sound(); // Will call Cat's sound() due to late binding

return 0;
}
Explanation:
• Animal has a virtual function sound().
• Dog and Cat override this function with their own versions.
• In the main() function, animalPtr is a base class pointer (Animal*), but it points to
derived class objects (Dog and Cat). The call to sound() is resolved at runtime based
on the type of the object being pointed to (Dog or Cat). This is an example of
dynamic binding (or late binding).

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 2


SHRI SHANKARACHARYA TECHNICAL CAMPUS

• The correct version of sound() is called based on the actual type of the object (Dog or
Cat), not the type of the pointer.

Example 2: Pure Virtual Function and Abstract Class


we demonstrate how to create an abstract class with a pure virtual function. An abstract class
cannot be instantiated directly, and it must be inherited by derived classes, which must
implement the pure virtual function.
#include <iostream>
using namespace std;

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

class Circle : public Shape {


public:
void draw() override { // Implementation of draw() in derived class
cout << "Drawing Circle" << endl;
}
};

class Rectangle : public Shape {


public:
void draw() override { // Implementation of draw() in derived class
cout << "Drawing Rectangle" << endl;
}
};

int main() {
Shape* shapePtr;

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 3


SHRI SHANKARACHARYA TECHNICAL CAMPUS

Circle circle;
Rectangle rectangle;

shapePtr = &circle;
shapePtr->draw(); // Calls Circle's draw()

shapePtr = &rectangle;
shapePtr->draw(); // Calls Rectangle's draw()

return 0;
}
Explanation:
• Shape is an abstract class because it has a pure virtual function draw() (= 0).
• Both Circle and Rectangle inherit from Shape and implement the draw() function.
• In main(), shapePtr is a pointer to Shape, but it points to instances of Circle and
Rectangle. When shapePtr->draw() is called, C++ will dynamically resolve the call to
the appropriate draw() method based on the actual type of the object (Circle or
Rectangle).
• This example demonstrates polymorphism where the same method draw() behaves
differently based on the object type at runtime.

Demonstrating Virtual Function with Destructor


We demonstrate how virtual destructors work in C++. If a base class has a virtual function, its
destructor should also be declared virtual to ensure proper cleanup of resources when an
object is deleted via a base class pointer.
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Base class constructor" << endl; }
virtual ~Base() { cout << "Base class destructor" << endl; } // Virtual destructor
};

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 4


SHRI SHANKARACHARYA TECHNICAL CAMPUS

class Derived : public Base {


public:
Derived() { cout << "Derived class constructor" << endl; }
~Derived() { cout << "Derived class destructor" << endl; } // Destructor
};

int main() {
Base* basePtr = new Derived();
delete basePtr; // Destructor of both Base and Derived will be called
return 0;
}
Explanation:
• Base class has a virtual destructor. This is important for proper destruction of
derived class objects when they are deleted via a base class pointer.
• If the destructor in the base class is not virtual, only the base class destructor will be
called when an object is deleted using a base class pointer (delete basePtr), leading to
resource leaks or incomplete cleanup.
• Since Base's destructor is virtual, both the Derived class's destructor and the Base
class's destructor are called when the object is deleted, ensuring proper cleanup of
resources.

Virtual Functions and Function Overriding


how overriding virtual functions works, where the derived class provides its own version of a
base class function.
#include <iostream>
using namespace std;

class Animal {
public:
virtual void speak() { cout << "Animal speaks" << endl; } // Virtual function
};

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 5


SHRI SHANKARACHARYA TECHNICAL CAMPUS

class Dog : public Animal {


public:
void speak() override { cout << "Dog barks" << endl; } // Override
};

class Cat : public Animal {


public:
void speak() override { cout << "Cat meows" << endl; } // Override
};

int main() {
Animal* animalPtr;

Dog dog;
Cat cat;

animalPtr = &dog;
animalPtr->speak(); // Calls Dog's speak()

animalPtr = &cat;
animalPtr->speak(); // Calls Cat's speak()

return 0;
}
Explanation:
• speak() is a virtual function in the Animal class.
• Dog and Cat override the speak() function to provide their own behavior.
• The function calls to animalPtr->speak() invoke the overridden speak() method based
on the actual type of object (Dog or Cat) that animalPtr points to.

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 6


SHRI SHANKARACHARYA TECHNICAL CAMPUS

Bindings
In C++, binding refers to the linking of a function call to the actual code that will be
executed. Binding can happen at compile time (known as early binding) or at runtime
(known as late binding). Here’s a breakdown of these concepts along with examples.

Early Binding (Static Binding)


Early Binding happens at compile time. The compiler determines which function to call
based on the type of the object or pointer. This is typically the default behavior in C++.
Since the function to call is determined at compile time, early binding is fast but doesn’t
support polymorphism.
Early Binding:
#include <iostream>
using namespace std;

class Animal {
public:
void sound() { // Regular function, not virtual
cout << "Animal sound" << endl;
}
};

class Dog : public Animal {


public:
void sound() { // Regular function, overrides sound() in base class
cout << "Barking" << endl;
}
};

int main() {
Animal animal;
Dog dog;

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 7


SHRI SHANKARACHARYA TECHNICAL CAMPUS

animal.sound(); // Calls Animal's sound() due to early binding


dog.sound(); // Calls Dog's sound() due to early binding

Animal* ptr = &dog;


ptr->sound(); // Still calls Animal's sound() due to early binding

return 0;
}
Explanation:
• Here, sound() is a regular function in both Animal and Dog.
• Since sound() is not virtual, the call to sound() is determined based on the type of the
pointer, not the object it points to.
• Therefore, ptr->sound() calls Animal::sound(), even though ptr points to a Dog object.
This is an example of early binding.

Late Binding (Dynamic Binding)


Late Binding happens at runtime. It is enabled using virtual functions. In this case, the
function to be called is determined based on the actual type of the object that a pointer or
reference points to. Late binding supports polymorphism and is slower than early binding due
to the runtime overhead of determining the correct function.
Late Binding with Virtual Function:
#include <iostream>
using namespace std;
class Animal {
public:
virtual void sound() { // Virtual function for late binding
cout << "Animal sound" << endl;
}
};

class Dog : public Animal {


public:

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 8


SHRI SHANKARACHARYA TECHNICAL CAMPUS

void sound() override { // Overrides the base class function


cout << "Barking" << endl;
}
};

int main() {
Animal* animalPtr;
Dog dog;

animalPtr = &dog;
animalPtr->sound(); // Calls Dog's sound() due to late binding

return 0;
}
Explanation:
• Here, sound() is a virtual function in Animal, allowing it to be overridden in Dog.
• When animalPtr->sound() is called, it calls the overridden Dog::sound() function
because of late binding.
• C++ determines at runtime that animalPtr points to a Dog object, so it calls
Dog::sound() instead of Animal::sound().

Virtual Functions
A virtual function is a function in a base class that you expect to override in derived classes.
It enables late binding and allows for polymorphic behavior. Virtual functions are typically
used to ensure that the correct function in a derived class is called when using base class
pointers or references.
Example of Virtual Function:
cpp
Copy code
#include <iostream>
using namespace std;

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 9


SHRI SHANKARACHARYA TECHNICAL CAMPUS

class Shape {
public:
virtual void draw() { // Virtual function
cout << "Drawing shape" << endl;
}
};

class Circle : public Shape {


public:
void draw() override { // Overrides base class function
cout << "Drawing circle" << endl;
}
};

int main() {
Shape* shapePtr;
Circle circle;

shapePtr = &circle;
shapePtr->draw(); // Calls Circle's draw() due to virtual function

return 0;
}
Explanation:
• The draw() function in Shape is a virtual function.
• Circle overrides draw() with its own implementation.
• When shapePtr->draw() is called, it calls the overridden version in Circle because of
the virtual function, even though shapePtr is a pointer to Shape.

Pure Virtual Functions and Abstract Classes

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 10


SHRI SHANKARACHARYA TECHNICAL CAMPUS

A pure virtual function is a virtual function that has no implementation in the base class and
is assigned 0. A class with one or more pure virtual functions is called an abstract class.
Abstract classes cannot be instantiated directly; they are designed to act as a base class for
other classes.
Pure Virtual Function and Abstract Class:
#include <iostream>
using namespace std;

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

class Circle : public Shape {


public:
void draw() override { // Must override the pure virtual function
cout << "Drawing circle" << endl;
}
};

class Square : public Shape {


public:
void draw() override { // Must override the pure virtual function
cout << "Drawing square" << endl;
}
};

int main() {
Shape* shapePtr;
Circle circle;
Square square;

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 11


SHRI SHANKARACHARYA TECHNICAL CAMPUS

shapePtr = &circle;
shapePtr->draw(); // Calls Circle's draw()

shapePtr = &square;
shapePtr->draw(); // Calls Square's draw()

return 0;
}
Explanation:
• Shape has a pure virtual function draw(), making Shape an abstract class.
• Circle and Square inherit from Shape and override draw() with specific
implementations.
• Shape* shapePtr can point to either Circle or Square objects, and the correct draw()
function is called at runtime due to late binding enabled by the pure virtual function.

Exception Handling in C++


Exception handling in C++ is a mechanism that allows programs to deal with unexpected
situations or errors in a controlled way. When an error occurs, it "throws" an exception, and
the program can catch the exception and take corrective action rather than abruptly
terminating.
C++ provides three primary keywords for exception handling:
• try: Block of code that may throw an exception.
• catch: Block of code that handles the exception.
• throw: Used to trigger (throw) an exception.
The process involves:
1. Throwing an exception when an error occurs.
2. Catching the exception with a catch block where error handling takes place.
3. Resuming normal program flow if possible.

Basic Structure of Exception Handling


Here's the general structure for exception handling:

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 12


SHRI SHANKARACHARYA TECHNICAL CAMPUS

try {
// Code that may throw an exception
throw exception; // Throws an exception
}
catch (type_of_exception) {
// Code to handle the exception
}
Example 1: Basic Exception Handling with Division by Zero
A simple example where we try to perform division and catch a division-by-zero error.
#include <iostream>
using namespace std;

int main() {
int numerator = 10;
int denominator = 0;
try {
if (denominator == 0)
throw "Division by zero error"; // Throwing an exception
cout << "Result: " << numerator / denominator << endl;
}
catch (const char* e) { // Catching the exception
cout << "Error: " << e << endl;
}
return 0;
}
Explanation:
• If denominator is zero, the throw statement is executed, throwing a string as an
exception.
• The catch block catches this exception and displays an error message.
• This prevents the program from crashing and instead displays a user-friendly error
message.

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 13


SHRI SHANKARACHARYA TECHNICAL CAMPUS

Example 2: Multiple catch Blocks for Different Exceptions


You can have multiple catch blocks to handle different types of exceptions, such as integer,
floating-point, and string types.
#include <iostream>
using namespace std;

int main() {
try {
int choice;
cout << "Enter 1 to throw integer, 2 to throw double, 3 to throw string: ";
cin >> choice;

if (choice == 1)
throw 100; // Throw an integer
else if (choice == 2)
throw 99.99; // Throw a double
else if (choice == 3)
throw "Exception string"; // Throw a string
}
catch (int e) {
cout << "Caught an integer: " << e << endl;
}
catch (double e) {
cout << "Caught a double: " << e << endl;
}
catch (const char* e) {
cout << "Caught a string: " << e << endl;
}

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 14


SHRI SHANKARACHARYA TECHNICAL CAMPUS

return 0;
}

Explanation:
• Depending on the user's input, an exception of a specific type is thrown.
• Different catch blocks handle each exception type separately.
• The correct catch block is selected based on the type of the exception thrown,
showcasing the flexibility of C++ exception handling.

Example 3: Catch-All Exception Handler


A catch block that handles all types of exceptions can be implemented using the ellipsis (...).
This catch-all handler is useful when we do not know in advance what kind of exception
might occur.
#include <iostream>
using namespace std;

int main() {
try {
throw 404; // Throwing an integer exception
}
catch (int e) {
cout << "Caught an integer: " << e << endl;
}
catch (...) { // Catch-all handler
cout << "Caught an unknown exception" << endl;
}
return 0;
}
Explanation:
• The catch(...) block catches any type of exception, regardless of its type.
• If an exception is thrown that doesn’t match any previous catch block, the catch-all
handler will catch it.
SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 15
SHRI SHANKARACHARYA TECHNICAL CAMPUS

Example 4: Rethrowing an Exception


Sometimes an exception may need to be handled at a higher level, so it can be re-thrown
after being caught.
#include <iostream>
using namespace std;

void functionA() {
try {
throw "Error occurred in functionA"; // Throw an exception
}
catch (const char* e) {
cout << "Caught in functionA: " << e << endl;
throw; // Rethrow the exception to main()
}
}

int main() {
try {
functionA();
}
catch (const char* e) {
cout << "Caught in main: " << e << endl;
}
return 0;
}
Explanation:
• functionA() throws an exception and catches it, then re-throws it.

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 16


SHRI SHANKARACHARYA TECHNICAL CAMPUS

• In main(), the re-thrown exception is caught again, demonstrating that exceptions can
propagate through multiple levels if necessary.

Example 5: Using Exception Handling with User-Defined Classes


You can throw and catch objects of user-defined classes, making exception handling more
structured and specific.
#include <iostream>
#include <string>
using namespace std;

class DivideByZeroException {
public:
string message;
DivideByZeroException(string msg) : message(msg) {}
};

double divide(double a, double b) {


if (b == 0)
throw DivideByZeroException("Division by zero exception"); // Throw an exception
object
return a / b;
}

int main() {
try {
cout << "Result: " << divide(10, 0) << endl;
}
catch (DivideByZeroException& e) { // Catch the custom exception
cout << "Caught an exception: " << e.message << endl;
}

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 17


SHRI SHANKARACHARYA TECHNICAL CAMPUS

return 0;
}
Explanation:
• DivideByZeroException is a custom exception class with a message property.
• divide() throws a DivideByZeroException if the denominator is zero.
• In main(), we catch this specific exception type and print the error message, making
the exception handling more meaningful and informative.
Specifying Exceptions (Deprecated in C++ 11 and Removed in C++ 17)
In older C++ standards, you could specify the types of exceptions a function could throw
using the throw() keyword, such as void func() throw(int, double);. However, this
approach has been deprecated and is no longer used in modern C++.
In C++11 and later, the recommended way is to avoid specifying exception types and use
exception-safe practices. Instead, the noexcept keyword indicates that a function does not
throw exceptions, which can optimize performance.
Example (Deprecated):
// Not recommended in C++11 and later
void func() throw(int, double) {
// Function that may throw int or double exceptions
}
Using noexcept:
#include <iostream>
using namespace std;

void safeFunction() noexcept {


cout << "This function is guaranteed not to throw an exception." << endl;
}

int main() {
safeFunction();
return 0;
}
Explanation:

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 18


SHRI SHANKARACHARYA TECHNICAL CAMPUS

• safeFunction is marked with noexcept, which indicates it won’t throw an exception.


• Using noexcept can help the compiler optimize the code, as it doesn’t need to set up
exception-handling mechanisms for this function.

1. Template Concepts
which are a mechanism to impose constraints on template parameters. Concepts enhance
templates by specifying requirements that types must satisfy to be used with the template.
template <typename T>
concept ConceptName = <constraint_expression>;

template <ConceptName T>


void func(T value) {
// Function body
}
Example:
#include <concepts>
#include <iostream>

// Concept for types supporting addition


template <typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::convertible_to<T>;
};

template <Addable T>


T add(T a, T b) {
return a + b;
}

int main() {
std::cout << add(3, 5) << '\n'; // Valid
SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 19
SHRI SHANKARACHARYA TECHNICAL CAMPUS

// std::cout << add(3, "Hello"); // Error: incompatible types


}
Concepts validate template arguments during compilation.
They can simplify code readability and provide better diagnostics.
2. Function Templates
Function templates allow you to write generic functions that can operate on different data
types without rewriting the same code for each type.
Syntax
cpp
Copy code
template <typename T>
ReturnType functionName(Parameters) {
// Function body
}
Example
cpp
Copy code
#include <iostream>
template <typename T>
T findMax(T a, T b) {
return (a > b) ? a : b;
}

int main() {
std::cout << findMax(10, 20) << '\n'; // Calls with int
std::cout << findMax(10.5, 7.8) << '\n'; // Calls with double
}
Key Points:
• The typename keyword can be replaced with class.
• Function templates are instantiated at compile time when called with specific types.

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 20


SHRI SHANKARACHARYA TECHNICAL CAMPUS

3. Class Templates
Class templates allow the creation of generic classes where the data type can be specified
when an object is instantiated.
Syntax
template <typename T>
class ClassName {
// Members and methods
};
Example
#include <iostream>
template <typename T>
class Box {
T value;

public:
Box(T val) : value(val) {}
void display() {
std::cout << "Value: " << value << '\n';
}
};

int main() {
Box<int> intBox(10); // Integer specialization
Box<double> doubleBox(3.14); // Double specialization

intBox.display();
doubleBox.display();
}
• The class template is instantiated when an object is created with a specific type.

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 21


SHRI SHANKARACHARYA TECHNICAL CAMPUS

• Class templates can have multiple type parameters: template <typename T1,
typename T2>.

Files:
File handling in C++ involves working with files using input/output streams to perform
operations like reading, writing, and updating data. Here's a detailed explanation of key
concepts in file handling:

1. File Streams
File streams are objects in C++ used to handle file input and output operations. The file
stream classes in the <fstream> header provide mechanisms for file handling. The primary
file stream classes are:
• ifstream: For input (reading from files).
• ofstream: For output (writing to files).
• fstream: For both input and output.
Basic Syntax
#include <fstream>
// Creating file stream objects
std::ifstream inputFile; // Input stream
std::ofstream outputFile; // Output stream
std::fstream file; // Input/Output stream

2. Hierarchy of File Stream Classes


C++ organizes file streams into a hierarchy, derived from the base class ios. The hierarchy is
as follows:
ios (base class)
├── istream (for input)
│ └── ifstream
├── ostream (for output)
│ └── ofstream
└── iostream (for input/output)
└── fstream

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 22


SHRI SHANKARACHARYA TECHNICAL CAMPUS

Key Member Functions (Common Across Classes):


• open(): Opens a file.
• close(): Closes a file.
• eof(): Checks if the end of the file is reached.
• fail(): Checks if an operation failed.
• good(): Checks if a stream is in a good state.

3. Error Handling During File Operations


To ensure robust file handling, error checking is essential. Common techniques include:
• Using member functions like fail() or eof().
• Checking the success of open() or file stream operations.
Example
#include <iostream>
#include <fstream>

int main() {
std::ifstream file("example.txt");

if (!file) {
std::cerr << "Error: File could not be opened.\n";
return 1;
}

std::cout << "File opened successfully.\n";


file.close();
return 0;
}
4. Reading and Writing Files
File operations involve opening a file, performing read or write operations, and closing the
file.

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 23


SHRI SHANKARACHARYA TECHNICAL CAMPUS

Writing to a File
#include <iostream>
#include <fstream>
int main() {
std::ofstream outFile("output.txt");
if (!outFile) {
std::cerr << "Error opening file for writing.\n";
return 1;
}
outFile << "Hello, World!\n";
outFile << "Writing to a file in C++.\n";
outFile.close();
return 0;
}
Reading from a File
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream inFile("output.txt");
std::string line;
if (!inFile) {
std::cerr << "Error opening file for reading.\n";
return 1;
}
while (std::getline(inFile, line)) {
std::cout << line << '\n';
}
inFile.close();
return 0;

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 24


SHRI SHANKARACHARYA TECHNICAL CAMPUS

5. Accessing Records Randomly


C++ allows random access to file data using the following functions:
• seekg(offset, direction): Moves the get pointer for input operations.
• seekp(offset, direction): Moves the put pointer for output operations.
• tellg(): Returns the current position of the get pointer.
• tellp(): Returns the current position of the put pointer.
Example: Random Access
#include <iostream>
#include <fstream>
int main() {
std::fstream file("random.txt", std::ios::in | std::ios::out | std::ios::trunc);
file << "ABCDEFGHIJKLMNO"; // Write some data
file.seekp(5); // Move the put pointer to position 5
file << "123"; // Overwrite at position 5
file.seekg(0); // Move the get pointer to the start
char ch;
while (file.get(ch)) {
std::cout << ch; // Display the file content
}
file.close();
return 0;
}

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 25


SHRI SHANKARACHARYA TECHNICAL CAMPUS

6. Updating Files
Updating files involves modifying the content of an existing file. You can read data, modify it
in memory, and then write it back.

Example: Updating a File


#include <iostream>
#include <fstream>
#include <string>
int main() {
std::fstream file("update.txt", std::ios::in | std::ios::out);
if (!file) {
std::cerr << "Error opening file for updating.\n";
return 1;
}
std::string line;
while (std::getline(file, line)) {
if (line == "old_data") {
file.seekp(file.tellg() - static_cast<std::streamoff>(line.size() + 1)); // Move back to
overwrite
file << "new_data";
}
}
file.close();
return 0;
}

SOMESH KUMAR DEWANGAN DEPARTMENT OF CSE 26

You might also like