Unit 2 QB Oop
Unit 2 QB Oop
Analyze the three primary access modifiers in C++: public, private, and
protected. How do they differ in their control of access?
Access Accessibility Use Case
Modifier
Public Accessible from anywhere. Used for methods and members meant
for public interaction.
Private Accessible only within the class. Used for sensitive data and internal
methods.
Protected Accessible within the class and Used for data or methods that derived
derived classes. classes can use.
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Base {
public:
int publicVar = 1;
private:
int privateVar = 2;
protected:
int protectedVar = 3;
};
int main() {
Derived d;
d.show();
// cout << d.protectedVar; // Error: protectedVar is inaccessible
return 0;
}
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Rectangle {
int length, width;
public:
// Default constructor
Rectangle() : length(0), width(0) {}
// Parameterized constructor
Rectangle(int l, int w) : length(l), width(w) {}
// Single-parameter constructor
Rectangle(int side) : length(side), width(side) {}
int main() {
Rectangle r1; // Default constructor
Rectangle r2(10, 5); // Parameterized constructor
Rectangle r3(7); // Single-parameter constructor
cout << "Area (r1): " << r1.area() << endl;
cout << "Area (r2): " << r2.area() << endl;
cout << "Area (r3): " << r3.area() << endl;
return 0;
}
Output:
mathematica
Copy code
Area (r1): 0
Area (r2): 50
Area (r3): 49
Code Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Counter {
private:
static int count; // Static data member
public:
Counter() { count++; } // Increment count for each object
static int getCount() { return count; } // Static member function
};
int main() {
Counter c1, c2, c3; // Increment count for each object
cout << "Count: " << Counter::getCount() << endl; // Access using
class name
return 0;
}
Output:
makefile
Copy code
Count: 3
Static Initialization:
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Box {
int length;
public:
Box(int l) : length(l) {}
void display() { cout << "Length: " << length << endl; }
};
int main() {
Box boxes[3] = { Box(5), Box(10), Box(15) }; // Static
initialization
for (int i = 0; i < 3; i++)
boxes[i].display();
return 0;
}
Dynamic Initialization:
Example:
cpp
Copy code
int n;
cout << "Enter number of boxes: ";
cin >> n;
Box* boxes = new Box[n] { Box(5), Box(10) }; // Dynamic initialization
delete[] boxes; // Free memory
Code Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Account {
string name;
double balance;
public:
void get_Account_Details() {
cout << "Enter account holder name: ";
cin >> name;
cout << "Enter balance: ";
cin >> balance;
}
void display_Account_Details() {
cout << "Account Holder: " << name << endl;
cout << "Balance: " << balance << endl;
}
};
int main() {
Account acc;
acc.get_Account_Details();
acc.display_Account_Details();
return 0;
}
● Access modifiers define how class members (data and functions) can be accessed.
● They ensure data protection and controlled interaction.
1. Public:
○ Members are accessible from anywhere.
○ Example: Methods that provide public interfaces.
2. Private:
○ Members are accessible only within the class.
○ Example: Sensitive data like account balance.
3. Protected:
○ Members are accessible within the class and derived classes.
○ Example: Attributes shared with derived classes but hidden from the outside.
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Car {
string model;
int year;
public:
Car() { model = "Default"; year = 0; } // Default constructor
Car(string m, int y) : model(m), year(y) {} // Parameterized
constructor
void display() {
cout << "Model: " << model << ", Year: " << year << endl;
}
};
int main() {
Car car1; // Default constructor
Car car2("Sedan", 2020); // Parameterized constructor
car1.display();
car2.display();
return 0;
}
Output:
yaml
Copy code
Model: Default, Year: 0
Model: Sedan, Year: 2020
8. Write a C++ program to implement the member functions
get_Employee_Details() and display_Employee_Details(). Also,
write a suitable main function to demonstrate the class.
Code Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Employee {
string name;
int id;
double salary;
public:
void get_Employee_Details() {
cout << "Enter name: ";
cin >> name;
cout << "Enter ID: ";
cin >> id;
cout << "Enter salary: ";
cin >> salary;
}
void display_Employee_Details() {
cout << "Name: " << name << ", ID: " << id << ", Salary: " <<
salary << endl;
}
};
int main() {
Employee emp;
emp.get_Employee_Details();
emp.display_Employee_Details();
return 0;
}
9. Analyze the significance of incorporating multiple constructors in a class
and evaluate this concept with an example to illustrate its practical
importance.
Significance:
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Student {
string name;
int age;
public:
Student() { name = "Unknown"; age = 0; } // Default
Student(string n, int a) : name(n), age(a) {} // Parameterized
void display() { cout << "Name: " << name << ", Age: " << age <<
endl; }
};
int main() {
Student s1; // Default
Student s2("Alice", 21); // Parameterized
s1.display();
s2.display();
return 0;
}
Output:
yaml
Copy code
Name: Unknown, Age: 0
Name: Alice, Age: 21
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Product {
string name;
double price;
public:
void setData(string n, double p) {
name = n;
price = p;
}
void display() {
cout << "Product: " << name << ", Price: $" << price << endl;
}
};
int main() {
Product products[3]; // Array of objects
Output:
yaml
Copy code
Product: Laptop, Price: $999.99
Product: Phone, Price: $499.99
Product: Tablet, Price: $299.99
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value;
Example(int v) : value(v) {}
void display() { cout << "Value: " << value << endl; }
};
// Passing by value
void byValue(Example obj) {
obj.value = 20;
}
// Passing by reference
void byReference(Example& obj) {
obj.value = 30;
}
// Passing by pointer
void byPointer(Example* obj) {
obj->value = 40;
}
int main() {
Example obj(10);
cout << "Original object value: ";
obj.display();
byValue(obj);
cout << "After byValue call: ";
obj.display();
byReference(obj);
cout << "After byReference call: ";
obj.display();
byPointer(&obj);
cout << "After byPointer call: ";
obj.display();
return 0;
}
● When passing an object by value, a copy of the object is created within the function. Any
modifications to this copy do not affect the original object.
● Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value;
Example(int v) : value(v) {}
};
int main() {
Example obj(50);
cout << "Original object value: " << obj.value << endl;
modifyObject(obj);
cout << "Object value after modifyObject call: " << obj.value <<
endl;
return 0;
}
● The value in obj remains unchanged after the modifyObject call because only a
copy was passed.
● Multiple constructors provide flexibility in initializing objects in various ways. This can
simplify code and improve readability.
● Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value1;
double value2;
int main() {
Example obj1; // Uses default constructor
Example obj2(10); // Uses parameterized constructor (int)
Example obj3(20, 5.5); // Uses parameterized constructor (int,
double)
cout << "obj1: value1 = " << obj1.value1 << ", value2 = " <<
obj1.value2 << endl;
cout << "obj2: value1 = " << obj2.value1 << ", value2 = " <<
obj2.value2 << endl;
cout << "obj3: value1 = " << obj3.value1 << ", value2 = " <<
obj3.value2 << endl;
return 0;
}
● Arrays of objects allow creating multiple instances of a class at once. Such arrays can be
declared and manipulated similarly to arrays of primitive types.
● Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value;
Example(int v) : value(v) {}
void display() { cout << "Value: " << value << endl; }
};
int main() {
Example arr[3] = { Example(10), Example(20), Example(30) };
return 0;
}
class Example {
public:
int value1;
double value2;
int main() {
Example obj1;
Example obj2(10);
Example obj3(20, 5.5);
Example obj4 = obj3; // Copy constructor
cout << "obj1: value1 = " << obj1.value1 << ", value2 = " <<
obj1.value2 << endl;
cout << "obj2: value1 = " << obj2.value1 << ", value2 = " <<
obj2.value2 << endl;
cout << "obj3: value1 = " << obj3.value1 << ", value2 = " <<
obj3.value2 << endl;
cout << "obj4: value1 = " << obj4.value1 << ", value2 = " <<
obj4.value2 << endl;
return 0;
}
class Student {
public:
string name;
int rollNo;
void getStudentDetails() {
cout << "Enter student name: ";
cin >> name;
cout << "Enter roll number: ";
cin >> rollNo;
}
return 0;
}
class Example {
public:
static int count; // Static data member
Example() {
count++;
}
void displayCount() {
cout << "Count: " << count << endl;
}
};
int main() {
Example obj1, obj2, obj3;
obj1.displayCount();
obj2.displayCount();
obj3.displayCount();
return 0;
}
● Multiple constructors offer flexibility in initializing objects in various ways, enabling easier
construction depending on the situation.
● Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value;
Example() : value(0) {} // Default constructor
Example(int v) : value(v) {} // Parameterized constructor
Example(const Example& obj) : value(obj.value) {} // Copy
constructor
};
int main() {
Example obj1;
Example obj2(10);
Example obj3 = obj2;
return 0;
}
19. Evaluate the best practices for selecting appropriate access modifiers
based on design and security requirements in object-oriented
programming.
● The access modifiers public, private, and protected help manage the visibility
and accessibility of class members and methods.
● Use private for members that should be hidden from the outside world, protected
for derived class access, and public for members that should be accessible from
outside the class.
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value1;
double value2;
int main() {
Example obj1;
Example obj2(10);
Example obj3(20, 5.5);
cout << "obj1: value1 = " << obj1.value1 << ", value2 = " <<
obj1.value2 << endl;
cout << "obj2: value1 = " << obj2.value1 << ", value2 = " <<
obj2.value2 << endl;
cout << "obj3: value1 = " << obj3.value1 << ", value2 = " <<
obj3.value2 << endl;
return 0;
}
● Pass by Value: A copy of the object is passed. Changes to the object inside the function
do not affect the original object.
● Pass by Reference: A reference to the object is passed, meaning modifications inside
the function affect the original object. This is more efficient than passing by value,
especially for large objects.
● Pass by Pointer: Similar to pass by reference, but the function works with a pointer to
the object. The object can be modified, and the memory location can be changed within
the function.
● Pass by Const Reference: A reference to the object is passed, but the object cannot be
modified. This avoids copying and allows safe access to large objects.
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value;
Example(int v) : value(v) {}
// Pass by value
void passByValue(Example obj) {
obj.value = 10;
}
// Pass by reference
void passByReference(Example& obj) {
obj.value = 20;
}
// Pass by pointer
void passByPointer(Example* obj) {
obj->value = 30;
}
int main() {
Example obj(5);
passByValue(obj);
passByReference(obj);
passByPointer(&obj);
passByConstReference(obj);
● Advantages:
○ Safety: The original object is not modified, which can be beneficial if the function
should not alter the object.
○ Isolation: Since a copy is made, there’s no risk of unintended side effects from
modifying the original object.
● Disadvantages:
○ Performance: Copying large objects can be inefficient, especially if the
constructor for the object is complex or contains dynamic memory.
○ Memory Usage: Memory is consumed to store the copy, which could be costly
for large objects.
In general, if the object is large or the function doesn't need to modify it, passing by reference
(especially const reference) is preferable.
23. Develop a C++ class that demonstrates the declaration and definition of
static data members. Implement methods to access these static members
both through member functions and directly from the class.
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
static int count; // Static data member
Example() {
count++;
}
int main() {
Example obj1, obj2;
Example::displayCount(); // Access static member via class name
obj1.displayCount(); // Access static member via object
return 0;
}
● Note: Static data members are shared across all instances of a class, and they must be
defined outside the class.
24. Explain the three main access modifiers in C++: public, private, and
protected. How do they differ in terms of access control?
Example:
cpp
Copy code
class Example {
public:
int publicValue; // Can be accessed from anywhere
private:
int privateValue; // Can only be accessed within the class
protected:
int protectedValue; // Can be accessed within the class and
derived classes
};
int main() {
Example obj;
obj.publicValue = 10; // Allowed
// obj.privateValue = 20; // Error: private member
// obj.protectedValue = 30; // Error: protected member
return 0;
}
25. Design a C++ program that demonstrates the concept of an array of
objects. Implement a class with a member function that takes an array of
objects as an argument.
cpp
Copy code
#include <iostream>
using namespace std;
class Student {
public:
string name;
int rollNo;
void display() {
cout << "Name: " << name << ", Roll No: " << rollNo << endl;
}
};
int main() {
Student students[3] = { Student("Alice", 101), Student("Bob",
102), Student("Charlie", 103) };
displayStudents(students, 3);
return 0;
}
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value;
int main() {
Example obj1;
Example obj2(10);
Example obj3 = obj2;
return 0;
}
27. Create a class that uses both parameterized and copy constructors.
Show how these constructors can be used in an array of objects, ensuring
proper memory management using the destructor.
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int value;
Example() : value(0) {}
Example(int v) : value(v) {}
Example(const Example& obj) : value(obj.value) {}
~Example() { cout << "Destructor called for value: " << value <<
endl; }
};
int main() {
Example arr[3] = { Example(10), Example(20), Example(30) };
return 0; // Destructor will be called here
}
28. Create a C++ class that demonstrates both the need for a custom
destructor and the scenarios where the default destructor is sufficient.
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int* ptr;
Example(int val) {
ptr = new int(val);
}
~Example() {
delete ptr;
cout << "Memory freed!" << endl;
}
};
int main() {
Example obj(10);
return 0; // Destructor is called here, freeing memory
}
● Move Constructors:
○ Advantages: More efficient than copy constructors, especially for objects that
manage dynamic memory or other resources.
○ Disadvantages: Move constructors can leave the original object in an invalid or
"moved-from" state, so care must be taken when using them.
cpp
Copy code
#include <iostream>
#include <string>
using namespace std;
class Example {
public:
string* data;
Example(string str) {
data = new string(str);
}
// Move constructor
Example(Example&& other) noexcept : data(other.data) {
other.data = nullptr;
}
~Example() {
delete data;
}
void display() {
cout << *data << endl;
}
};
int main() {
Example obj1("Hello");
Example obj2 = std::move(obj1); // Move constructor is called
obj2.display();
}
● Constructor Order: In C++, base class constructors are called before derived class
constructors. This ensures that the base class is properly initialized before the derived
class uses it.
● Destructor Order: The order is reversed; derived class destructors are called first,
followed by the base class destructors, ensuring proper cleanup of resources in the
derived class before the base class.
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
public:
int x;
int y;
// Default constructor
Example() : Example(0, 0) {} // Delegates to the parameterized
constructor
// Parameterized constructor
Example(int a, int b) : x(a), y(b) {}
void display() {
cout << "x: " << x << ", y: " << y << endl;
}
};
int main() {
Example obj1; // Calls default constructor, which delegates
to the parameterized constructor
Example obj2(10, 20);
obj1.display(); // x: 0, y: 0
obj2.display(); // x: 10, y: 20
return 0;
}
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class Example {
private:
int* ptr;
public:
// Parameterized constructor
Example(int value) {
ptr = new int; // Dynamically allocate memory
*ptr = value; // Initialize with the provided value
}
// Destructor
~Example() {
delete ptr; // Free the dynamically allocated memory
cout << "Memory freed!" << endl;
}
int main() {
Example obj(42);
obj.display(); // Displays the value of the dynamically
allocated memory
return 0; // Destructor is called here, memory is freed
}
The destructor is essential for cleaning up any resources allocated by the constructor, especially
dynamic memory, to avoid memory leaks.
Example:
cpp
Copy code
#include <iostream>
using namespace std;
class DynamicMemoryManager {
private:
int* data;
public:
// Constructor that allocates dynamic memory
DynamicMemoryManager(int value) {
data = new int; // Dynamically allocated memory
*data = value; // Initialize with the provided value
}
int main() {
DynamicMemoryManager obj(100); // Object is created, memory is
allocated
obj.display(); // Display the value stored in
dynamically allocated memory
● In this example, new is used in the constructor to allocate memory for data, and the
delete operator in the destructor ensures that memory is freed when the object goes
out of scope, preventing memory leaks