0% found this document useful (0 votes)
12 views20 pages

cs201 Lec 34 To 40

The document covers various concepts in C++ programming, including arrays of objects, dynamic arrays, operator overloading for memory management, and stream handling for input/output. It explains how to manipulate data formatting using manipulators and user-defined functions, as well as the use of static variables and pointers. Additionally, it discusses memory allocation techniques and the differences between call by value and call by reference.

Uploaded by

maryamwaris0109
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)
12 views20 pages

cs201 Lec 34 To 40

The document covers various concepts in C++ programming, including arrays of objects, dynamic arrays, operator overloading for memory management, and stream handling for input/output. It explains how to manipulate data formatting using manipulators and user-defined functions, as well as the use of static variables and pointers. Additionally, it discusses memory allocation techniques and the differences between call by value and call by reference.

Uploaded by

maryamwaris0109
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/ 20

📘 Lecture 34

🔹 1) Arrays of Objects

📖 Definition:
An array of objects means creating multiple objects of a class using an array, just like an array
of integers or strings.

It helps you store and manage many objects of the same class together.

✅ Example:

#include <iostream>
using namespace std;

class Student {
public:
void show() {
cout << "I am a student" << endl;
}
};

int main() {
Student s[3]; // Create an array of 3 Student objects

// Call the show() function for each student


s[0].show();
s[1].show();
s[2].show();

return 0;
}

💬 Explanation:

• We made a class Student.


• Then created 3 students using an array: Student s[3];
• Each student can call functions independently.

🔹 2) Dynamic Arrays of Objects

📖 Definition:
Dynamic arrays are created at runtime using new. You can decide the number of objects while
the program is running, not before.
✅ Example:

#include <iostream>
using namespace std;

class Student {
public:
void show() {
cout << "Dynamic student" << endl;
}
};

int main() {
Student* s = new Student[2]; // Creates 2 Student objects dynamically

s[0].show(); // Call show() for first object


s[1].show(); // Call show() for second object

delete[] s; // Always free the memory after use

return 0;
}

💬 Explanation:

• We used new to create a dynamic array of Student.


• Used delete[] to clean the memory.

🔹 3) Overloading new and delete Operators

📖 Definition:
You can customize how memory is allocated and deallocated for objects by overloading the
new and delete operators inside a class.

✅ Example:

#include <iostream>
#include <cstdlib> // for malloc and free
using namespace std;

class MyClass {
public:
// Overload new operator
void* operator new(size_t size) {
cout << "Custom new operator called" << endl;
return malloc(size); // Allocate memory manually
}

// Overload delete operator


void operator delete(void* ptr) {
cout << "Custom delete operator called" << endl;
free(ptr); // Free memory manually
}
};

int main() {
MyClass* obj = new MyClass(); // Calls custom new
delete obj; // Calls custom delete
return 0;
}

💬 Explanation:

• newand delete are redefined.


• Now, whenever we create or delete an object, our custom message and logic is used.

🔹 4) Example of Overloading new and delete as Non-members

📖 Definition:
We can also overload new and delete globally (outside the class) to apply to all objects in the
program.

✅ Example:

#include <iostream>
#include <cstdlib>
using namespace std;

// Global overload of new


void* operator new(size_t size) {
cout << "Global new called" << endl;
return malloc(size);
}

// Global overload of delete


void operator delete(void* ptr) noexcept {
cout << "Global delete called" << endl;
free(ptr);
}

class MyClass {
int x;
};

int main() {
MyClass* obj = new MyClass; // Will call global new
delete obj; // Will call global delete
return 0;
}
💬 Explanation:

• This applies new and delete to all classes, unless class-specific ones are defined.

🔹 5) Overloading new and delete as Members

📖 Definition:
This means writing new and delete inside a specific class to control memory only for that
class.

✅ Already shown above in point 3.

💬 Explanation:

• These are useful when a class needs special memory handling (e.g., logging or debugging
memory usage).

🔹 6) Overloading [] Operator to Create Arrays

📖 Definition:
You can overload the [] operator so you can use array-like indexing on your custom object.

✅ Example:

#include <iostream>
using namespace std;

class Marks {
int arr[5]; // internal array
public:
Marks() {
for (int i = 0; i < 5; i++) {
arr[i] = i * 10; // Fill array with values 0, 10, 20, 30, 40
}
}

// Overload [] operator
int operator[](int index) {
return arr[index]; // Return value at given index
}
};

int main() {
Marks m;
cout << "Value at index 2: " << m[2] << endl; // Output: 20
return 0;
}

💬 Explanation:

• We created a class with an array.


• Used operator[] so we can write m[2] like a normal array.

📗 Lecture 35 — Input/Output Streams

🔹 1) Streams

📖 Definition:
A stream is a path through which data flows. In C++, data can flow:

• Into a program from the keyboard (input stream like cin)


• Out of a program to the screen (output stream like cout)

✅ Example:

#include <iostream>
using namespace std;

int main() {
int age;

// Ask the user to enter age


cout << "Enter your age: "; // Output stream (cout)

cin >> age; // Input stream (cin) gets value from keyboard

cout << "Your age is: " << age << endl; // Display the value

return 0;
}

💬 Explanation in comments:

• cout is used to display output (to screen)


• cin is used to take input (from keyboard)
• These are examples of streams
🔹 2) Source and Destination of Streams

📖 Definition:
In a stream:

• Source is where data comes from (e.g., keyboard)


• Destination is where data goes to (e.g., screen)

✅ Example:

#include <iostream>
using namespace std;

int main() {
int number;

// Keyboard (source) → number (destination)


cout << "Enter a number: ";
cin >> number;

// number (source) → Screen (destination)


cout << "You entered: " << number << endl;

return 0;
}

💬 Explanation:

• When using cin, source = keyboard, destination = variable


• When using cout, source = variable, destination = screen

🔹 3) Formatted Input and Output

📖 Definition:
Formatted I/O means controlling how data is shown, e.g., using width, precision, alignment,
etc., using iomanip library.

✅ Example:

#include <iostream>
#include <iomanip> // for formatting
using namespace std;

int main() {
float pi = 3.14159;
// Set width and precision for output
cout << "Value of pi with 2 decimal places: " << fixed << setprecision(2)
<< pi << endl;

// setw(10) sets field width to 10 spaces


cout << setw(10) << 42 << endl;

return 0;
}

💬 Explanation:

• setprecision(2) sets 2 digits after decimal


• setw(10) reserves 10 spaces to print value

🔹 4) Recap Streams

📖 Definition:
Streams are used for:

• Reading input (cin)


• Writing output (cout)
• Reading from files (ifstream)
• Writing to files (ofstream)

They make input/output easier and more flexible.

✅ Quick Recap Code:

#include <iostream>
#include <fstream> // for file streams
using namespace std;

int main() {
ofstream file("data.txt"); // Output stream to file
file << "Hello File"; // Write to file
file.close();

return 0;
}

💬 Explanation:

• ofstream is an output file stream (writes to a file).


• C++ streams are not just for screen/keyboard — they work with files too.
🔹 5) Buffered Input/Output

📖 Definition:
Buffered I/O stores input/output in a temporary memory area (buffer). It sends/receives data
in chunks for better performance.

✅ Example:

#include <iostream>
using namespace std;

int main() {
cout << "This is buffered output";

// Buffer is flushed (output sent to screen) only when endl or flush is


used
cout << endl; // flushes the buffer

return 0;
}

💬 Explanation:

• endlflushes (empties) the buffer and sends output to screen.


• Without flushing, output may stay in memory for a moment.

🔹 6) Methods with Streams

📖 Definition:
Streams have built-in methods like:

• .get() – reads a character


• .put() – writes a character
• .ignore() – skips input
• .eof() – checks end of file

✅ Example:

#include <iostream>
using namespace std;

int main() {
char ch;
cout << "Enter any character: ";
cin.get(ch); // gets a single character including whitespace

cout.put(ch); // prints the character

return 0;
}

💬 Explanation:

• get() is used to take a single character (including spaces)


• put() is used to output a single character

🔹 7) Examples Using Streams

📖 Definition:
You can use streams for both file and keyboard/screen I/O.

✅ Example: Read and write file

#include <iostream>
#include <fstream>
using namespace std;

int main() {
ofstream outFile("test.txt"); // Create file and open for writing
outFile << "Learning C++ Streams"; // Write to file
outFile.close(); // Close file

string content;
ifstream inFile("test.txt"); // Open same file for reading
getline(inFile, content); // Read line from file

cout << "File says: " << content << endl;


inFile.close();

return 0;
}

💬 Explanation:

• ofstream writes to file


• ifstream reads from file
• getline() reads a full line from file
✅ Summary Table
Topic What it Means
Streams Flow of input/output data
Source & Destination Where data comes from/goes to
Formatted I/O Control how data is displayed
Buffered I/O Temp memory used for faster I/O
Stream Methods Functions like get(), put(), eof()
Using Streams Input/output from screen and files

✅ Lecture 36

37) Stream Manipulations

These are ways to control how data is input/output in C++.


They help format numbers, text, and align content in the console output.

38) Manipulators

Special functions in C++ used to format output like setting width, precision, etc.
Examples: setw(), setprecision(), endl, etc.

39) Non-Parameterized Manipulators

These manipulators don't take any values.


Example: endl is used to insert a newline.

#include <iostream>
using namespace std;

int main() {
cout << "Hello" << endl; // ends line
cout << "World";
return 0;
}
40) Parameterized Manipulators

They take arguments to modify the output format.


Used with iomanip header.

#include <iostream>
#include <iomanip> // for setw and setprecision
using namespace std;

int main() {
cout << setw(10) << 123 << endl; // width = 10
cout << setprecision(4) << 3.14159; // 4 total digits
return 0;
}

41) Format State Flags

Flags used to set output behavior like base, sign, alignment, etc.
Example: cout.setf(ios::showpos) shows + sign for positive numbers.

42) Formatting Manipulation

Combining manipulators and flags to control formatting of output.


For example, controlling left/right alignment or showing decimal points.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
cout.setf(ios::left); // left align
cout << setw(10) << "Name" << "Age\n";
cout << setw(10) << "Ali" << 20;
return 0;
}

43) Showing the Base

Use manipulators to show the base of numbers like hexadecimal or octal.

#include <iostream>
using namespace std;

int main() {
int x = 255;
cout << showbase; // show base
cout << hex << x << endl; // hexadecimal with base
cout << oct << x << endl; // octal with base
return 0;
}

44) Scientific Representation

Used to show floating point numbers in scientific (exponential) form.

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
double num = 123456.789;
cout << scientific << num; // scientific format
return 0;
}

45) Exercise

Try this:

• Print a float in scientific form


• Print a number in hex with base
• Align three names in left and right alignment using setw()

✅ Lecture 37

Overloading Insertion and Extraction Operators

We can customize how objects are printed or read using << and >>.

#include <iostream>
using namespace std;

class Student {
int roll;
public:
Student(int r) { roll = r; }

// Overload <<
friend ostream& operator<<(ostream& out, Student s) {
out << "Roll No: " << s.roll;
return out;
}
};

int main() {
Student s1(101);
cout << s1; // Will call the overloaded << function
return 0;
}

✅ Lecture 38

46) User Defined Manipulator

You can create your own manipulator like endl for custom output formatting.

#include <iostream>
using namespace std;

// User-defined manipulator
ostream& myEndl(ostream& out) {
out << "\n----------\n";
return out;
}

int main() {
cout << "Hello" << myEndl << "World";
return 0;
}

47) Examples of User Defined Manipulator

You can define multiple manipulators for custom spacing, headers, etc.

ostream& showStars(ostream& out) {


out << "\n*****\n";
return out;
}
48) Static Keyword

static keeps a variable's value even after the function ends.


It's also used for class-level variables shared among all objects.

#include <iostream>
using namespace std;

void test() {
static int count = 0;
count++;
cout << count << endl;
}

int main() {
test(); test(); test(); // Output: 1 2 3
return 0;
}

49) Static Objects

Static objects are created only once, and destroyed at the end of the program.

class Demo {
public:
Demo() { cout << "Constructor\n"; }
~Demo() { cout << "Destructor\n"; }
};

int main() {
static Demo obj; // lives till end of program
}

50) Static Data Members of a Class

A static data member is shared by all objects of the class.

#include <iostream>
using namespace std;

class Student {
public:
static int count;

Student() { count++; }
};

int Student::count = 0;

int main() {
Student s1, s2;
cout << "Total Students: " << Student::count;
return 0;
}

✅ Lecture 39
✅ 51) Pointers

A pointer is a variable that stores the memory address of another variable.

int a = 10;
int* ptr = &a; // ptr stores the address of a
cout << *ptr; // prints the value of a using pointer

✅ 52) References

A reference is just another name (alias) for an existing variable. It must be initialized when
declared.

int a = 5;
int& ref = a; // ref is another name for a
ref = 10; // a is now 10

✅ 53) Call by Value

When using call by value, a copy of the variable is passed, so the original value doesn’t change.

void func(int x) {
x = 20;
}
int main() {
int a = 10;
func(a);
cout << a; // Output: 10 (original unchanged)
}

✅ 54) Call by Reference

In call by reference, the original variable is passed, so changes are reflected.


void func(int &x) {
x = 20;
}
int main() {
int a = 10;
func(a);
cout << a; // Output: 20
}

✅ 55) Dynamic Memory Allocation

We use new and delete to create and free memory at runtime.

int* p = new int; // dynamically allocate memory


*p = 50;
cout << *p; // Output: 50
delete p; // free memory

✅ 56) Assignment and Initialization

Initialization happens when you declare and assign a value.


Assignment happens after the variable is already created.

int a = 5; // Initialization
a = 10; // Assignment

✅ 57) Copy Constructor

A special constructor that is called when a new object is created from an existing object.

class Test {
public:
int x;
Test(int a) { x = a; }
Test(const Test &t) { x = t.x; } // Copy constructor
};

✅ 58) Example (Copy Constructor)


class Test {
public:
int x;
Test(int a) { x = a; }
Test(const Test &obj) { x = obj.x; }
};
int main() {
Test t1(10);
Test t2 = t1; // Copy constructor called
cout << t2.x; // Output: 10
}

✅ 59) Rules for Using Dynamic Memory Allocation

1. Always delete memory allocated using new.


2. Avoid memory leaks by freeing memory.
3. Initialize pointers to nullptr.

✅ 60) Usage of Copy Constructor

Used:

• When an object is passed by value to a function.


• When an object is returned from a function.
• When one object is used to initialize another.

✅ 61) Summary

• Pointer: Stores address.


• Reference: Alias.
• Call by Value: Original not affected.
• Call by Reference: Original changes.
• Dynamic Allocation: Uses new/delete.
• Copy Constructor: Copies object values safely.
✅ Lecture 40
This lecture focuses on object composition, where objects of one class are used inside another
class. It's a core part of Object-Oriented Programming (OOP) and helps create complex
structures from simpler parts.

✅ Objects as Class Members

When you create an object of one class inside another class, it is called an object as a class
member (also called composition).

✅ Why use it?

To reuse code and build complex structures by combining simpler objects.

✅ Example 1: Object as a Member


class Address {
public:
string city;
int zip;

void setAddress(string c, int z) {


city = c;
zip = z;
}

void display() {
cout << "City: " << city << ", ZIP: " << zip << endl;
}
};

class Student {
public:
string name;
Address addr; // Object of Address inside Student

void setStudent(string n, string c, int z) {


name = n;
addr.setAddress(c, z); // Using Address class functions
}

void display() {
cout << "Name: " << name << endl;
addr.display();
}
};

int main() {
Student s1;
s1.setStudent("Ali", "Lahore", 54000);
s1.display();
}

✅ Example 2: Nested Object with Constructor


class Date {
public:
int day, month, year;
Date(int d, int m, int y) {
day = d; month = m; year = y;
}
};

class Person {
public:
string name;
Date birthDate; // Composition

// Constructor initialization list used for object inside class


Person(string n, Date d) : name(n), birthDate(d) {}

void display() {
cout << "Name: " << name << ", DOB: "
<< birthDate.day << "/" << birthDate.month << "/" <<
birthDate.year << endl;
}
};

int main() {
Date d(10, 7, 2000);
Person p("Sara", d);
p.display();
}

✅ Advantages of Objects as Class Members

1. Code Reusability – Use existing class objects.


2. Modular Code – Break into smaller, manageable parts.
3. Clean Design – Logical relationships are easier to model (e.g., a Student has an
Address).

✅ Structures as Class Members


struct Result {
float marks;
string grade;
};

class Student {
public:
string name;
Result res; // Structure as member

void setData(string n, float m, string g) {


name = n;
res.marks = m;
res.grade = g;
}

void display() {
cout << "Name: " << name << ", Marks: " << res.marks << ", Grade: "
<< res.grade << endl;
}
};

✅ Classes inside Classes (Nested Classes)

You can define a class inside another class. This is called a nested class.

class Outer {
public:
class Inner {
public:
void show() {
cout << "Inside Inner class" << endl;
}
};
};

int main() {
Outer::Inner obj;
obj.show();
}

✅ Tips

• When using objects as members, constructors of those objects are called automatically.
• Use initialization lists in constructors when member objects don’t have default
constructors.
• Nested classes are useful for tightly coupling small helper classes.

You might also like