oop_solutionsew d
oop_solutionsew d
This document provides model solutions to the chapterwise-sorted past year questions (Papers A–D, see com-
panion question file). Programs are kept simple and exam-appropriate; theory answers are concise.
1
Circle(float r){ radius = r; }
float area(){ return 3.14 * radius * radius; }
};
int main(){
Circle c(5);
cout << "Area = " << [Link]() << endl;
return 0;
}
2
}
int main(){
printMessage("Hello"); // uses default count = 1
printMessage("Welcome", 3); // prints 3 times
return 0;
}
Q2 (B) – Namespace
Namespace is a feature in C++ that provides a named scope to group related identifiers (variables, functions,
classes) and avoid name collisions, especially when combining code from multiple libraries.
Why needed: Large programs often use multiple libraries that may define identifiers with the same name.
Without namespaces, this causes naming conflicts. Namespaces let us use the same name in different scopes
without clashing.
#include <iostream>
using namespace std;
namespace First{
int value = 100;
void display(){ cout << "First::value = " << value << endl; }
}
namespace Second{
int value = 200;
void display(){ cout << "Second::value = " << value << endl; }
}
int main(){
First::display();
Second::display();
cout << "Directly: " << First::value + Second::value << endl;
return 0;
}
int main(){
cout << "Square of 5 = " << square(5) << endl;
return 0;
}
Function overloading: Defining multiple functions with the same name but different parameter lists
(different number/type of parameters). The compiler chooses the correct version based on the arguments
passed (compile-time polymorphism).
#include <iostream>
using namespace std;
3
int add(int a, int b){ return a + b; }
double add(double a, double b){ return a + b; }
int add(int a, int b, int c){ return a + b + c; }
int main(){
cout << add(2, 3) << endl; // int version
cout << add(2.5, 3.5) << endl; // double version
cout << add(1, 2, 3) << endl; // three-arg version
return 0;
}
int main(){
cout << "A (custom r) = " << compoundAmount(1000, 2, 10) << endl;
cout << "A (default r=50) = " << compoundAmount(1000, 2) << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
class Person{
private:
string name, address;
int age;
long citizenship_number;
public:
// Parameterized constructor
Person(string n, int a, string addr, long cn){
name = n; age = a; address = addr;
if(age > 16)
citizenship_number = cn;
4
else
citizenship_number = 0;
}
void display(){
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
cout << "Address: " << address << endl;
cout << "Citizenship No: " << citizenship_number << endl;
}
};
int main(){
Person p1("Ram", 20, "Kathmandu", 123456);
Person p2("Sita", 12, "Pokhara", 654321);
[Link]();
[Link]();
return 0;
}
#include <iostream>
using namespace std;
class A{
private:
int valA;
public:
A(int v) : valA(v) {}
// declare a specific member function of B as friend
friend void B::showBoth(A &a);
};
class B{
private:
int valB;
public:
B(int v) : valB(v) {}
void showBoth(A &a){
cout << "A’s private valA = " << [Link] << endl;
cout << "B’s valB = " << valB << endl;
}
};
5
Note: because B::showBoth uses A’s private member, B must be declared before A (or use forward declaration
as above) and A must friend that specific function of B.
Friend class example (object passed/returned):
#include <iostream>
using namespace std;
class Box{
private:
int length;
public:
Box(int l=0): length(l) {}
friend class BoxPrinter; // entire class is friend
};
class BoxPrinter{
public:
void print(Box b){ // object passed by value
cout << "Length = " << [Link] << endl;
}
Box makeBox(){ // returning an object
Box temp(10);
return temp;
}
};
int main(){
BoxPrinter bp;
Box b1 = [Link](); // object returned from function
[Link](b1); // object passed to function
return 0;
}
Condition for friend class: when two classes are closely related and one needs direct access to the private/pro-
tected data of the other for efficiency or design reasons (e.g., operator overloading involving two classes, linked
data structures).
#include <iostream>
#include <string>
using namespace std;
class Information{
private:
string name, address;
public:
Information(string n, string a) : name(n), address(a) {}
void display(){
cout << "Name: " << name << ", Address: " << address << endl;
}
friend void swapInfo(Information &s1, Information &s2);
6
};
int main(){
Information s1("Ram", "Kathmandu");
Information s2("Hari", "Pokhara");
cout << "Before swap:\n";
[Link](); [Link]();
swapInfo(s1, s2);
cout << "After swap:\n";
[Link](); [Link]();
return 0;
}
class Time{
private:
int hour, minute, second;
public:
Time(int h, int m, int s) : hour(h), minute(m), second(s) {}
friend Time add(Time t1, Time t2);
void display(){
cout << hour << " hr : " << minute << " min : " << second << " sec" << endl;
}
};
int main(){
Time t1(5, 45, 50);
Time t2(3, 30, 20);
Time result = add(t1, t2);
cout << "Aggregate Time: ";
[Link]();
return 0;
}
7
Chapter 4: Operator Overloading
General rules for operator overloading (applies to all four below):
Only existing operators can be overloaded; new operators cannot be created.
At least one operand must be a user-defined type (class object).
Operators ::, ., .*, ?:, sizeof cannot be overloaded.
Precedence and associativity of an operator cannot be changed.
Overloading is done using the keyword operator (e.g. operator+).
Unary operators take no explicit argument (if member function); binary operators take one explicit argu-
ment (if member function) or two (if non-member/friend).
#include <iostream>
using namespace std;
class Matrix{
private:
int m[3][3];
public:
void input(){
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
cin >> m[i][j];
}
Matrix operator+(Matrix M){
Matrix temp;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
temp.m[i][j] = m[i][j] + M.m[i][j];
return temp;
}
Matrix operator-(Matrix M){
Matrix temp;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
temp.m[i][j] = m[i][j] - M.m[i][j];
return temp;
}
void display(){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++)
cout << m[i][j] << " ";
cout << endl;
}
}
};
int main(){
Matrix A, B, C, D;
cout << "Enter elements of matrix A:\n"; [Link]();
cout << "Enter elements of matrix B:\n"; [Link]();
C = A + B;
D = A - B;
cout << "Sum:\n"; [Link]();
cout << "Difference:\n"; [Link]();
return 0;
}
8
Q4 (B) – Non-member Operator Overloading: Complex Numbers
#include <iostream>
using namespace std;
class Complex{
private:
float real, imag;
public:
Complex(float r=0, float i=0) : real(r), imag(i) {}
void display(){
cout << real << " + " << imag << "i" << endl;
}
friend Complex operator+(Complex, Complex);
friend Complex operator-(Complex, Complex);
friend Complex operator*(Complex, Complex);
friend Complex operator/(Complex, Complex);
};
int main(){
Complex c1(4, 5), c2(2, 3);
(c1+c2).display();
(c1-c2).display();
(c1*c2).display();
(c1/c2).display();
return 0;
}
#include <iostream>
using namespace std;
class Time{
private:
int hour, minute, second;
public:
Time(int h=0, int m=0, int s=0) : hour(h), minute(m), second(s) {}
// post-increment: dummy int parameter distinguishes from pre-increment
Time operator++(int){
9
Time temp = *this; // save old value
second++;
if(second >= 60){ second = 0; minute++; }
if(minute >= 60){ minute = 0; hour++; }
return temp;
}
void display(){
cout << hour << ":" << minute << ":" << second << endl;
}
};
int main(){
Time t1(10, 59, 59);
Time t2 = t1++; // post-increment
cout << "Before increment (t2): "; [Link]();
cout << "After increment (t1): "; [Link]();
return 0;
}
#include <iostream>
using namespace std;
class Length{
private:
int meter, centimeter;
public:
Length(int m, int c) : meter(m), centimeter(c) {}
int totalCm(){
return meter * 100 + centimeter;
}
bool operator>(Length L){
return (this->totalCm() > [Link]());
}
};
int main(){
Length l1(5, 40);
Length l2(4, 90);
if(l1 > l2)
cout << "Length 1 is greater" << endl;
else
cout << "Length 2 is greater or equal" << endl;
return 0;
}
Chapter 5: Inheritance
Q5 (A) – Private vs Protected; Function Overriding; Cricketer Hierarchy
Private vs Protected:
private: members are accessible only within the same class, not even by derived classes.
protected: members are accessible within the same class and by derived classes, but not from outside.
Function overriding: when a derived class defines a function with the same name and signature as one in
its base class, the derived class’s version is called for derived class objects (redefinition of base behavior).
10
#include <iostream>
#include <string>
using namespace std;
class Cricketer{
protected:
string name;
int age, matches;
public:
Cricketer(string n, int a, int m) : name(n), age(a), matches(m) {}
void display(){
cout << "Name: " << name << ", Age: " << age << ", Matches: " << matches << endl;
}
};
int main(){
Bowler b("Bumrah", 30, 100, 150);
Batsman s("Kohli", 35, 250, 12000, 45);
[Link]();
[Link]();
return 0;
}
Type of inheritance: Single inheritance (used twice – Bowler and Batsman each derive singly from Cricketer).
#include <iostream>
#include <string>
11
using namespace std;
class Person{
protected:
string name;
int age;
public:
Person(string n, int a) : name(n), age(a) {}
void display(){
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main(){
Student s("Mohan", 21, "Computer Engineering");
[Link]();
return 0;
}
#include <iostream>
using namespace std;
class A{
public:
A(){ cout << "Constructor of A called" << endl; }
};
class B : public A{
public:
B(){ cout << "Constructor of B called" << endl; }
};
class C : public B{
public:
C(){ cout << "Constructor of C called" << endl; }
};
int main(){
C obj; // constructors are called in order: A -> B -> C
return 0;
12
}
Output order: A’s constructor, then B’s, then C’s – base class constructors always run before the derived class
constructor, starting from the topmost base.
class A{
public:
int x = 10;
};
class B : virtual public A{};
class C : virtual public A{};
class D : public B, public C{};
int main(){
D d;
cout << d.x << endl; // no ambiguity due to virtual inheritance
return 0;
}
class Base{
public:
virtual ~Base(){ cout << "Base destructor" << endl; }
};
class Derived : public Base{
public:
~Derived(){ cout << "Derived destructor" << endl; }
};
int main(){
Base *b = new Derived();
delete b; // both destructors called because ~Base() is virtual
return 0;
13
}
class Employee{
protected:
string name;
float salary;
public:
Employee(string n, float s) : name(n), salary(s) {}
virtual void display(){
cout << "Employee: " << name << ", Salary: " << salary << endl;
}
virtual ~Employee() {}
};
int main(){
Employee *e = new Manager("Sita", 80000, "IT");
e->display(); // calls Manager::display() at run time (late binding)
delete e;
return 0;
}
class Shape{
public:
virtual float area() = 0; // pure virtual function -> abstract class
};
14
class Circle : public Shape{
private:
float radius;
public:
Circle(float r) : radius(r) {}
float area() override{
return 3.14 * radius * radius;
}
};
int main(){
Shape *s = new Circle(5);
cout << "Area: " << s->area() << endl;
delete s;
return 0;
}
class Employee{
protected:
string name;
public:
Employee(string n) : name(n) {}
virtual void display(){
cout << "Employee Name: " << name << endl;
}
virtual ~Employee(){ cout << "~Employee" << endl; }
};
class Student{
protected:
string roll;
public:
Student(string r) : roll(r) {}
virtual ~Student(){ cout << "~Student" << endl; }
};
15
Secretary(string n) : Employee(n) {}
~Secretary(){ cout << "~Secretary" << endl; }
};
int main(){
Employee *e1 = new Manager("Ram", "21001");
e1->display();
delete e1; // virtual destructor ensures ~Manager, ~Student, ~Employee all run
return 0;
}
int main(){
ofstream outFile("[Link]");
if(!outFile){ cout << "Error creating file" << endl; return 1; }
string text;
cout << "Enter text to write to source file: ";
getline(cin, text);
outFile << text;
[Link]();
16
cout << ch;
cout << endl;
[Link]();
return 0;
}
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Employee{
public:
string name;
int id;
int age;
float salary;
void getData(){
cout << "Enter name, id, age, salary: ";
cin >> name >> id >> age >> salary;
}
void showData(){
cout << name << "\t" << id << "\t" << age << "\t" << salary << endl;
}
};
int main(){
Employee e;
fstream file("[Link]", ios::out | ios::binary | ios::trunc);
for(int i = 0; i < 10; i++){
[Link]();
[Link]((char*)&e, sizeof(e));
}
[Link]();
// Search by employee ID
int searchId;
cout << "\nEnter employee ID to search: ";
cin >> searchId;
[Link]("[Link]", ios::in | ios::binary);
bool found = false;
17
while([Link]((char*)&e, sizeof(e))){
if([Link] == searchId){
cout << "Record found:\n";
[Link]();
found = true;
break;
}
}
if(!found) cout << "Record not found." << endl;
[Link]();
return 0;
}
class Student{
public:
int roll;
string name, address;
int batch;
void getData(){
cout << "Enter roll, name, address, batch: ";
cin >> roll >> name >> address >> batch;
}
void showData(){
cout << roll << "\t" << name << "\t" << address << "\t" << batch << endl;
}
};
int main(){
int n;
Student s;
cout << "Enter number of students: ";
cin >> n;
18
cin >> searchRoll;
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Book{
public:
int bookId;
string title, author;
void getData(){
cout << "Enter book ID, title, author: ";
cin >> bookId >> title >> author;
}
void showData(){
cout << bookId << "\t" << title << "\t" << author << endl;
}
};
int main(){
Book b;
ofstream outFile("[Link]", ios::binary);
cout << "Enter details of 5 books:\n";
for(int i = 0; i < 5; i++){
[Link]();
[Link]((char*)&b, sizeof(b));
}
[Link]();
19
return 0;
}
Chapter 8: Templates
Q8 (A) – Templates as Generic Programming; STL Containers/Iterators; Default Args in Class
Template
Templates as generic programming: Templates let a single function or class definition work with multiple
data types – the compiler generates a specific version for each type used, at compile time. This avoids writing
separate code for int, float, etc., embodying ”generic programming.”
STL Containers: data structures that store collections of objects, e.g. vector, list, map, set, stack,
queue.
STL Iterators: objects that point to elements of a container and allow traversal (like generalized pointers),
e.g. begin(), end().
#include <iostream>
using namespace std;
int main(){
Box<int> b1(10); // explicit type
Box<> b2(5); // uses default type (int)
Box<double> b3(3.14); // double type
[Link]();
[Link]();
[Link]();
return 0;
}
Q8 (B) – Code Redundancy via Templates; Sort n Numbers (Descending) using vector
Eliminating redundancy: Without templates, separate sort functions would be needed for int, float, etc.
A single function template works for any type.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
20
int main(){
int n;
cout << "Enter number of elements: ";
cin >> n;
vector<float> nums(n);
cout << "Enter " << n << " numbers: ";
for(int i = 0; i < n; i++) cin >> nums[i];
int main(){
cout << "Max int: " << findMax(10, 20) << endl;
cout << "Max double: " << findMax(3.5, 2.1) << endl;
This single findMax and Pair definition serves int, double, char (and any type supporting >) – demonstrating
reusable, type-independent code as claimed.
#include <iostream>
using namespace std;
21
class Item{
private:
T value;
public:
Item(T v = T()) : value(v) {} // default argument
void display(){ cout << "Value: " << value << endl; }
};
// Function template
template <class T>
T multiply(T a, T b){
return a * b;
}
int main(){
Item<int> i1; // uses default argument (0)
Item<int> i2(25);
[Link]();
[Link]();
Stack in STL: stack is a container adapter that provides LIFO (Last-In-First-Out) access. Defined in
<stack>, common operations: push() (insert at top), pop() (remove top), top() (access top element), empty(),
size(). Example: stack<int> s; [Link](10); [Link]();
class InvalidRoll{
public:
int roll;
InvalidRoll(int r) : roll(r) {}
};
class InvalidMarks{
public:
float marks;
InvalidMarks(float m) : marks(m) {}
};
int main(){
string name;
int roll;
float marks, fullMarks = 100;
22
cin >> name >> roll >> marks;
try{
if(roll < 0)
throw InvalidRoll(roll);
if(marks > fullMarks)
throw InvalidMarks(marks);
#include <iostream>
using namespace std;
int main(){
int a, b;
cout << "Enter two numbers: ";
cin >> a >> b;
try{
if(b == 0)
throw runtime_error("Division by zero!");
if(a < 0 || b < 0)
throw -1; // throwing an int
23
to detect and respond to such conditions without crashing the program.
#include <iostream>
using namespace std;
int main(){
int arr[5] = {1,2,3,4,5};
int index;
cout << "Enter index to access (0-4): ";
cin >> index;
try{
if(index < 0 || index >= 5)
throw out_of_range("Index out of bounds");
cout << "Value: " << arr[index] << endl;
int divisor;
cout << "Enter a divisor: ";
cin >> divisor;
if(divisor == 0)
throw runtime_error("Cannot divide by zero");
cout << "100 / divisor = " << 100/divisor << endl;
}
catch(out_of_range &e){
cout << "Error: " << [Link]() << endl;
}
catch(runtime_error &e){
cout << "Error: " << [Link]() << endl;
}
return 0;
}
#include <iostream>
#include <cmath>
using namespace std;
int main(){
double num;
cout << "Enter a number: ";
cin >> num;
try{
if(num < 0)
throw invalid_argument("Cannot compute square root of a negative number");
cout << "Square root = " << sqrt(num) << endl;
}
catch(invalid_argument &e){
cout << "Error: " << [Link]() << endl;
24
}
return 0;
}
25