0% found this document useful (0 votes)
17 views21 pages

Oops Pys Mid

The document covers various concepts of Object-Oriented Programming (OOP) in C++, including abstract classes, function calling methods, polymorphism, operator overloading, and inheritance. It provides code examples to illustrate these concepts, such as implementing abstract classes for different account types, demonstrating function overloading, and using virtual functions for polymorphism. Additionally, it discusses the use of static variables and functions, as well as the differences between private and protected inheritance.

Uploaded by

vermadhani633
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)
17 views21 pages

Oops Pys Mid

The document covers various concepts of Object-Oriented Programming (OOP) in C++, including abstract classes, function calling methods, polymorphism, operator overloading, and inheritance. It provides code examples to illustrate these concepts, such as implementing abstract classes for different account types, demonstrating function overloading, and using virtual functions for polymorphism. Additionally, it discusses the use of static variables and functions, as well as the differences between private and protected inheritance.

Uploaded by

vermadhani633
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/ 21

2022 PYQS OOPS – mid sems

(a) Abstract Class in C++

An abstract class in C++ is a class that contains at least one pure virtual function. It cannot be
instantiated but can serve as a base class for derived classes. A pure virtual function is a
function declared in a base class but must be overridden by derived classes.

Program to Implement an Abstract Class (Account) with Derived Classes (SavingAccount


and CurrentAccount):

cpp
CopyEdit
#include <iostream>
using namespace std;

// Abstract Class
class Account {
protected:
int accno;
string accname;
public:
Account(int a, string name) : accno(a), accname(name) {}

virtual void deposit(double amount) = 0; // Pure virtual function


virtual void withdraw(double amount) = 0; // Pure virtual function

void display() {
cout << "Account No: " << accno << ", Name: " << accname << endl;
}
};

// Derived Class - Savings Account


class SavingAccount : public Account {
private:
double balance;
public:
SavingAccount(int a, string name, double bal) : Account(a, name),
balance(bal) {}

void deposit(double amount) override {


balance += amount;
cout << "Deposited " << amount << " in Savings Account. New Balance:
" << balance << endl;
}

void withdraw(double amount) override {


if (balance >= amount) {
balance -= amount;
cout << "Withdrawn " << amount << " from Savings Account. New
Balance: " << balance << endl;
} else {
cout << "Insufficient Balance in Savings Account!" << endl;
}
}
};

// Derived Class - Current Account


class CurrentAccount : public Account {
private:
double balance;
public:
CurrentAccount(int a, string name, double bal) : Account(a, name),
balance(bal) {}

void deposit(double amount) override {


balance += amount;
cout << "Deposited " << amount << " in Current Account. New Balance:
" << balance << endl;
}

void withdraw(double amount) override {


if (balance >= amount) {
balance -= amount;
cout << "Withdrawn " << amount << " from Current Account. New
Balance: " << balance << endl;
} else {
cout << "Overdraft Not Allowed in Current Account!" << endl;
}
}
};

// Main Function
int main() {
// We cannot create an object of an abstract class, but we can use
pointers
Account* acc1 = new SavingAccount(101, "Alice", 5000);
Account* acc2 = new CurrentAccount(102, "Bob", 8000);

acc1->deposit(1000);
acc1->withdraw(2000);

acc2->deposit(1500);
acc2->withdraw(9000);

// Free allocated memory


delete acc1;
delete acc2;

return 0;
}

Can we create an object of an abstract class?

No, we cannot create an object of an abstract class, but we can create a pointer to it and use it to
access derived class objects.

(b) Function Calling Methods in C++

i) Difference Between Call by Value, Call by Reference, and Call by Pointer


Changes Reflected in
Method Definition Memory Usage Syntax
Caller?

Call by A copy of the argument is More (extra copy No (changes are made to the void
Value passed to the function is created) copy, not the original) func(int x)

Call by The actual argument is Less (no copy is Yes (changes affect the void
Reference passed using a reference (&) created) original variable) func(int &x)

Call by A pointer to the variable is Less (no copy is Yes (changes affect the void
Pointer passed created) original variable) func(int *x)

Example:

cpp
CopyEdit
#include <iostream>
using namespace std;

void callByValue(int x) {
x = x + 10;
cout << "Inside callByValue: " << x << endl;
}

void callByReference(int &x) {


x = x + 10;
cout << "Inside callByReference: " << x << endl;
}

void callByPointer(int *x) {


*x = *x + 10;
cout << "Inside callByPointer: " << *x << endl;
}

int main() {
int a = 5;

callByValue(a);
cout << "After callByValue: " << a << endl; // No change

callByReference(a);
cout << "After callByReference: " << a << endl; // Change reflected

callByPointer(&a);
cout << "After callByPointer: " << a << endl; // Change reflected

return 0;
}

ii) Function with Default Arguments

A function with default arguments allows you to define parameters with default values. If an
argument is not provided during the function call, the default value is used.

Example:

cpp
CopyEdit
#include <iostream>
using namespace std;
void greet(string name = "Guest") {
cout << "Hello, " << name << "!" << endl;
}

int main() {
greet(); // Uses default argument "Guest"
greet("Alice"); // Uses provided argument "Alice"
return 0;
}

Output:

CopyEdit
Hello, Guest!
Hello, Alice!

Key Points:

 Default arguments must be defined at the end of the parameter list.


 They allow function calls with fewer arguments while still handling optional parameters.

(a) Polymorphism with Student Class and Derived Classes


cpp
CopyEdit
#include <iostream>
using namespace std;

// Base class
class Student {
public:
virtual void details() { cout << "Student details\n"; }
};

// Derived class MCA


class MCA : public Student {
public:
void details() override { cout << "MCA Student details\n"; }
};

// Derived class BTech


class BTech : public Student {
public:
void details() override { cout << "B.Tech Student details\n"; }
};

// Derived class MTech


class MTech : public Student {
public:
void details() override { cout << "M.Tech Student details\n"; }
};
int main() {
Student* students[3]; // Array of pointers
students[0] = new MCA();
students[1] = new BTech();
students[2] = new MTech();

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


students[i]->details(); // Calls the overridden function
delete students[i]; // Clean up
}

return 0;
}

✔ Demonstrates polymorphism by overriding details() and calling it via base class


pointers.

(b) i) Overloading the + Operator


cpp
CopyEdit
#include <iostream>
using namespace std;

class Complex {
int real, imag;
public:
Complex(int r, int i) : real(r), imag(i) {}
Complex operator+(Complex obj) {
return Complex(real + obj.real, imag + obj.imag);
}
void display() { cout << real << " + " << imag << "i\n"; }
};

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

✔ Demonstrates operator overloading for adding complex numbers.

(b) ii) Static Variable in Function


cpp
CopyEdit
#include <iostream>
using namespace std;

void counter() {
static int count = 0; // Retains value between function calls
count++;
cout << "Function called " << count << " times\n";
}
int main() {
counter();
counter();
counter();
return 0;
}

✔ Demonstrates the use of static variable retaining its value across multiple function calls.

(a) i) Ambiguity Resolution using Virtual Base Class


cpp
CopyEdit
#include <iostream>
using namespace std;

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

class B : virtual public A {}; // Virtual base class


class C : virtual public A {}; // Virtual base class
class D : public B, public C {};

int main() {
D obj;
obj.show(); // No ambiguity due to virtual base class
return 0;
}

✔ Removes ambiguity by using virtual inheritance, ensuring only one copy of A exists in D.

(a) ii) Private and Protected Members of Class


cpp
CopyEdit
#include <iostream>
using namespace std;

class Base {
private:
int privateVar = 10;
protected:
int protectedVar = 20;
public:
int publicVar = 30;
int getPrivateVar() { return privateVar; } // Access private using public
method
};
class Derived : public Base {
public:
void show() {
// cout << privateVar; // Not accessible
cout << "Protected Var: " << protectedVar << endl; // Accessible
cout << "Public Var: " << publicVar << endl; // Accessible
}
};

int main() {
Derived obj;
obj.show();
cout << "Private Var using method: " << obj.getPrivateVar() << endl;
return 0;
}

✔ Private members are not inherited directly, but protected members are accessible in
derived classes.

(b) Operator Overloading for Time Class


cpp
CopyEdit
#include <iostream>
using namespace std;

class Time {
int hour, minute;
public:
Time(int h = 0, int m = 0) : hour(h), minute(m) {}

// Overloading unary ++ using member function


Time operator++() {
++minute;
if (minute >= 60) { minute = 0; ++hour; }
return *this;
}

// Overloading unary ++ using friend function


friend Time operator++(Time &t, int) {
Time temp = t;
t.minute++;
if (t.minute >= 60) { t.minute = 0; t.hour++; }
return temp;
}

void display() { cout << hour << " hr " << minute << " min\n"; }
};

int main() {
Time t1(2, 59);
cout << "Before increment: ";
t1.display();

++t1; // Calls member function


cout << "After prefix increment: ";
t1.display();

t1++; // Calls friend function


cout << "After postfix increment: ";
t1.display();
return 0;
}

✔ Demonstrates both member and friend function operator overloading for unary ++.

(a) Difference between new and delete

Feature new delete

Purpose Dynamically allocates memory Deallocates dynamically allocated memory


Returns Pointer to allocated memory Frees allocated memory
Usage int *ptr = new int; delete ptr;
Array Allocation int *arr = new int[5]; delete[] arr;

Function calc_avg() to calculate average of private members of two classes

cpp
CopyEdit
#include <iostream>
using namespace std;

class A {
private:
int num1;
public:
A(int x) : num1(x) {}
friend float calc_avg(A, B); // Declaring friend function
};

class B {
private:
int num2;
public:
B(int y) : num2(y) {}
friend float calc_avg(A, B); // Declaring friend function
};

// Function to calculate average (Not a member of any class)


float calc_avg(A obj1, B obj2) {
return (obj1.num1 + obj2.num2) / 2.0;
}

int main() {
A obj1(10);
B obj2(20);
cout << "Average: " << calc_avg(obj1, obj2) << endl;
return 0;
}

✔ Uses friend function to access private members and calculate the average.
(b) i) Compile-time and Runtime Polymorphism

Compile-time Polymorphism (Function Overloading)

cpp
CopyEdit
#include <iostream>
using namespace std;

class Poly {
public:
void show() { cout << "No arguments\n"; }
void show(int x) { cout << "Integer argument: " << x << endl; }
void show(double y) { cout << "Double argument: " << y << endl; }
};

int main() {
Poly obj;
obj.show();
obj.show(5);
obj.show(3.14);
return 0;
}

✔ Function overloading achieves compile-time polymorphism by resolving function calls at


compile-time.

Runtime Polymorphism (Function Overriding using Virtual Function)

cpp
CopyEdit
#include <iostream>
using namespace std;

class Base {
public:
virtual void display() { cout << "Base class\n"; } // Virtual function
};

class Derived : public Base {


public:
void display() override { cout << "Derived class\n"; }
};

int main() {
Base *ptr;
Derived obj;
ptr = &obj;
ptr->display(); // Calls Derived class function due to virtual function
return 0;
}

✔ Virtual functions allow method overriding, enabling runtime polymorphism.

(b) ii) Constructor and Destructor in Multilevel Inheritance


cpp
CopyEdit
#include <iostream>
using namespace std;

class A {
public:
A() { cout << "Constructor of A\n"; }
virtual ~A() { cout << "Destructor of A\n"; } // Virtual destructor
};

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

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

int main() {
A *ptr = new C();
delete ptr; // Proper destructor chaining due to virtual destructor
return 0;
}

✔ Virtual destructors ensure proper destruction of derived class objects in multilevel


inheritance.

PYQS 2022 OOPS – END SEMS

(a) i) Use of this Pointer


Definition:

 this is a pointer available in all non-static member functions of a class.


 It points to the current instance of the class.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Sample {
int x;
public:
Sample(int x) {
this->x = x; // Using 'this' to differentiate between local and
member variable
}
void display() {
cout << "Value of x: " << this->x << endl;
}
};

int main() {
Sample obj(10);
obj.display();
return 0;
}

✔ this is used to access member variables when there's a naming conflict.

(a) ii) Static Variables and Static Functions


Static Variables:

 Shared among all objects of a class.


 Retains value between function calls.
 Declared using static keyword.

Static Functions:

 Can access only static variables.


 Belongs to class, not to any object.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Counter {
static int count; // Static variable
public:
Counter() { count++; }
static void showCount() { // Static function
cout << "Count: " << count << endl;
}
};

int Counter::count = 0; // Initialization outside the class

int main() {
Counter obj1, obj2, obj3;
Counter::showCount(); // Accessing static function
return 0;
}

✔ Static variables retain values, and static functions operate at the class level.
(b) i) Private and Protected Derivation in Inheritance
Access Specifier Inheritance Type Access in Derived Class Access in Outside Class
private private Not accessible Not accessible
private protected Accessible as protected Not accessible
private public Accessible as public Not accessible

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Base {
private:
int privateVar = 10;
protected:
int protectedVar = 20;
public:
int publicVar = 30;
};

// Private Inheritance
class Derived1 : private Base {
public:
void show() {
// privateVar is NOT accessible
cout << "Protected Var: " << protectedVar << endl;
cout << "Public Var: " << publicVar << endl;
}
};

// Protected Inheritance
class Derived2 : protected Base {
public:
void show() {
// privateVar is NOT accessible
cout << "Protected Var: " << protectedVar << endl;
cout << "Public Var: " << publicVar << endl;
}
};

int main() {
Derived1 d1;
d1.show();

Derived2 d2;
d2.show();

return 0;
}

✔ Private members are never inherited, while protected members remain accessible in
derived classes.
(b) ii) Namespace in C++
Definition:

 Avoids name conflicts in large programs.


 Created using the namespace keyword.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

// Creating namespace
namespace MySpace {
int x = 10;
void display() { cout << "Inside MySpace: " << x << endl; }
}

int main() {
MySpace::display(); // Accessing namespace function
cout << "Value of x: " << MySpace::x << endl;
return 0;
}

✔ Namespaces prevent name collisions in large projects.

Q2 (a) i) Pure Virtual Functions


Definition:

 A pure virtual function is a function that has no definition in the base class.
 Declared using = 0 in the base class.
 Makes the class abstract, meaning it cannot be instantiated.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

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

class Circle : public Shape {


public:
void draw() override {
cout << "Drawing a Circle" << endl;
}
};

int main() {
// Shape s; // Error: Cannot instantiate abstract class
Circle c;
c.draw();
return 0;
}

✔ Pure virtual functions ensure that derived classes implement their own version of the
function.

Q2 (a) ii) Function Overloading


Definition:

 Multiple functions with the same name but different parameters.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Math {
public:
void add(int a, int b) {
cout << "Sum: " << a + b << endl;
}
void add(double a, double b) {
cout << "Sum (double): " << a + b << endl;
}
};

int main() {
Math obj;
obj.add(5, 3);
obj.add(2.5, 3.5);
return 0;
}

✔ The compiler differentiates functions based on parameter types and numbers.


Q2 (b) i) Ambiguity Resolution Using Scope Resolution
Operator (::)
Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Base {
public:
void show() {
cout << "Base class function" << endl;
}
};

class Derived : public Base {


public:
void show() {
cout << "Derived class function" << endl;
}
};

int main() {
Derived obj;
obj.show(); // Calls Derived class function
obj.Base::show(); // Calls Base class function
return 0;
}

✔ Scope resolution (::) is used to access the base class function explicitly.

Q2 (b) ii) Ambiguity Resolution Using Virtual Base Class


Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class A {
public:
void show() { cout << "A's function" << 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 due to virtual base class
return 0;
}

✔ Virtual base class prevents multiple copies of A in the inheritance chain.


Q3 (a) i) Inline Functions
Definition:

 A function that is expanded in-line at compile-time.


 Improves performance by avoiding function call overhead.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Test {
public:
inline void display() {
cout << "This is an inline function" << endl;
}
};

int main() {
Test t;
t.display();
return 0;
}

✔ Inlining is a compiler suggestion, not a strict rule.

Q3 (a) ii) Parameterized Constructor


Definition:

 A constructor that takes parameters for initialization.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Student {
int rollNo;
public:
Student(int r) { rollNo = r; }
void display() { cout << "Roll Number: " << rollNo << endl; }
};

int main() {
Student s1(101);
s1.display();
return 0;
}

✔ Parameterized constructors initialize objects with specific values.


Q3 (b) Overloading -- Operator (Prefix and Postfix)
Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Count {
int value;
public:
Count(int v) : value(v) {}

// Prefix decrement
Count operator--() {
--value;
return *this;
}

// Postfix decrement
Count operator--(int) {
Count temp = *this;
value--;
return temp;
}

void display() { cout << "Value: " << value << endl; }
};

int main() {
Count obj(10);

--obj; // Prefix
obj.display();

obj--; // Postfix
obj.display();

return 0;
}

✔ Both prefix (--obj) and postfix (obj--) decrement operators are overloaded.

Operators that Cannot Be Overloaded:

Operator Reason
:: (Scope Resolution) Defined at compile time
.* (Pointer-to-Member) Syntax complexity
sizeof Evaluated at compile time
typeid Used for RTTI (Run-Time Type Information)
Q4 (a) Difference Between a Function That is a Friend of
Two Classes and a Member Function That is a Friend of
Another Class
Friend Function of Two Classes

 A global function can be declared as friend in multiple classes.


 This function can access private members of both classes.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class B; // Forward declaration

class A {
int numA;
public:
A(int x) : numA(x) {}
friend void add(A, B); // Friend function
};

class B {
int numB;
public:
B(int y) : numB(y) {}
friend void add(A, B); // Friend function
};

void add(A objA, B objB) {


cout << "Sum: " << objA.numA + objB.numB << endl;
}

int main() {
A a(5);
B b(10);
add(a, b);
return 0;
}

✔ The friend function add() can access private data of both A and B.
Member Function That is a Friend of Another Class

 A member function of one class can be declared as a friend of another class.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class A {
int data;
public:
A(int x) : data(x) {}
friend class B; // Class B is a friend of A
};

class B {
public:
void showData(A obj) {
cout << "Data from A: " << obj.data << endl;
}
};

int main() {
A a(10);
B b;
b.showData(a);
return 0;
}

✔ Here, showData() (member of B) accesses private members of A.

Q4 (b) i) Difference Between Reference and Pointer


Reference:

 Alias for a variable.


 Cannot be NULL.
 Must be initialized at declaration.

Pointer:

 Stores the memory address of another variable.


 Can be reassigned to another address.

Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

int main() {
int x = 10;

int* ptr = &x; // Pointer


int& ref = x; // Reference
cout << "Pointer value: " << *ptr << endl;
cout << "Reference value: " << ref << endl;

return 0;
}

✔ Reference behaves like an alias, whereas a pointer stores addresses.

Q4 (b) ii) Rethrow an Exception


Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

void testFunction() {
try {
throw "Error occurred";
}
catch (const char* msg) {
cout << "Caught in function, rethrowing..." << endl;
throw; // Rethrow the same exception
}
}

int main() {
try {
testFunction();
}
catch (const char* msg) {
cout << "Caught in main: " << msg << endl;
}
return 0;
}

✔ Exception is caught in testFunction(), then rethrown and caught in main().

Q5 (a) Student Class with Constructor Overloading and


Array of Objects
Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

class Student {
static int rollCounter;
int rollNo;
string name;
float marks;
public:
Student(string n, float m) {
rollNo = rollCounter++;
name = n;
marks = m;
}

void display() {
cout << "Roll No: " << rollNo << ", Name: " << name << ", Marks: " <<
marks << endl;
}
};

// Initialize static member


int Student::rollCounter = 1001;

int main() {
Student students[3] = { Student("Alice", 90.5), Student("Bob", 88),
Student("Charlie", 92) };

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


students[i].display();
}

return 0;
}

✔ Each student gets a unique roll number starting from 1001.

Q5 (b) Exception Handling with Multiple catch Blocks


Example:
cpp
CopyEdit
#include <iostream>
using namespace std;

void testFunction(int x) {
if (x == 0) throw "Division by zero error";
if (x < 0) throw x;
if (x > 100) throw 3.14;
}

int main() {
try {
testFunction(0);
}
catch (const char* msg) {
cout << "Caught string exception: " << msg << endl;
}
catch (int x) {
cout << "Caught integer exception: " << x << endl;
}
catch (...) {
cout << "Caught unknown exception" << endl;
}
return 0;
}

✔ Demonstrates multiple catch blocks handling different exception types.

You might also like