BE Computer Engineering (IOE, TU) Object Oriented Programming (IOE, CT 501) Question Paper 2078 Nepal
This is the official BE Computer Engineering (IOE, TU) Object Oriented Programming (IOE, CT 501) question paper for 2078, as set in the regular annual examination. It carries 80 full marks and a time allowance of 180 minutes, across 12 questions. On Kekkei you can attempt this Object Oriented Programming (IOE, CT 501) past paper online with a timer, get instant AI feedback and step-by-step solutions, and track the topics where you lose marks — completely free. Whether you are revising for your BE Computer Engineering (IOE, TU) Object Oriented Programming (IOE, CT 501) exam or solving previous years' question papers, this 2078 paper is a great way to practise under real exam conditions.
Section A: Long Answer Questions
Attempt all / any as specified.
(a) Define a class and an object. Explain the difference between data members and member functions with a suitable example. [4]
(b) Write a complete C++ program to define a class Distance having data members feet and inches. Include a parameterized constructor to initialize the object, a member function to add two Distance objects, and a function to display the result. Demonstrate the use of the this pointer in your program. [8]
(a) Class and Object; Data Members vs Member Functions [4]
Class: A class is a user-defined data type that bundles together data (attributes) and functions (behaviour) into a single unit. It is only a blueprint/template and occupies no memory until an object is created.
Object: An object is an instance of a class. It is a concrete variable of the class type that occupies memory and holds actual values for the data members.
Data members vs Member functions:
| Data members | Member functions |
|---|---|
| Variables declared inside a class that hold the object's state | Functions declared inside a class that operate on the data members |
| Represent attributes | Represent behaviour |
Each object has its own copy (unless static) | One copy shared by all objects |
class Student {
string name; // data member (state)
int roll; // data member
public:
void setData(string n, int r) { name = n; roll = r; } // member function (behaviour)
void show() { cout << roll << " " << name << endl; } // member function
};
Here name, roll are data members, while setData() and show() are member functions that act on them.
(b) Distance class with parameterized constructor, add, display and this pointer [8]
#include <iostream>
using namespace std;
class Distance {
int feet;
int inches;
public:
// Parameterized constructor (using this pointer to disambiguate)
Distance(int feet, int inches) {
this->feet = feet;
this->inches = inches;
}
// Add the current object (this) with another Distance d
Distance add(const Distance &d) {
int totalInches = (this->feet * 12 + this->inches)
+ (d.feet * 12 + d.inches);
return Distance(totalInches / 12, totalInches % 12);
}
void display() {
cout << this->feet << " feet " << this->inches << " inches" << endl;
}
};
int main() {
Distance d1(5, 8);
Distance d2(3, 6);
Distance d3 = d1.add(d2); // d1 is 'this', d2 is the argument
cout << "Distance 1 : "; d1.display();
cout << "Distance 2 : "; d2.display();
cout << "Sum : "; d3.display();
return 0;
}
Output:
Distance 1 : 5 feet 8 inches
Distance 2 : 3 feet 6 inches
Sum : 9 feet 2 inches
Role of this: Inside any non-static member function, this is a pointer to the object on which the function was invoked. Here it both disambiguates the constructor parameters from the data members (this->feet = feet;) and explicitly refers to the calling object during addition.
(a) What is meant by virtual function? Explain how run-time polymorphism is achieved in C++ using virtual functions and base class pointers. [5]
(b) Write a C++ program that defines a base class Shape with a virtual function area(). Derive classes Circle and Rectangle from it, override area() in each, and use an array of base class pointers to compute and display the area of different shapes. [7]
(a) Virtual Functions and Run-time Polymorphism [5]
A virtual function is a member function declared with the keyword virtual in a base class and redefined (overridden) in a derived class. It tells the compiler to perform late (dynamic) binding — the function that actually executes is decided at run time based on the type of object the pointer/reference points to, not the static type of the pointer.
How run-time polymorphism is achieved:
- A base-class pointer (or reference) is made to point to a derived-class object:
Base *p = &derivedObj;. - The base class declares the function
virtual. - When
p->func()is called, the compiler does not bind the call at compile time. Instead the object carries a hidden pointer (vptr) to a table of function addresses (vtable). At run time the call is dispatched through the vtable to the overridden version belonging to the actual object. - Thus one interface (
p->func()) invokes different implementations depending on the object — "one interface, many forms".
This is why a virtual function must be called through a base pointer/reference; calling through an object directly uses static binding.
(b) Shape / Circle / Rectangle program [7]
#include <iostream>
using namespace std;
class Shape {
public:
virtual double area() = 0; // pure virtual -> abstract base
virtual ~Shape() {}
};
class Circle : public Shape {
double r;
public:
Circle(double r) : r(r) {}
double area() override { return 3.14159 * r * r; }
};
class Rectangle : public Shape {
double l, b;
public:
Rectangle(double l, double b) : l(l), b(b) {}
double area() override { return l * b; }
};
int main() {
Shape* shapes[2]; // array of base-class pointers
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
for (int i = 0; i < 2; i++)
cout << "Area = " << shapes[i]->area() << endl; // dynamic dispatch
for (int i = 0; i < 2; i++) delete shapes[i];
return 0;
}
Output:
Area = 78.5397
Area = 24
Because area() is virtual, shapes[i]->area() correctly calls Circle::area() then Rectangle::area() at run time.
(a) State the rules and restrictions for operator overloading in C++. Why can some operators not be overloaded? [4]
(b) Write a C++ program to create a class Complex for complex numbers and overload the + and * operators to add and multiply two complex numbers respectively. Implement at least one operator using a friend function. [8]
(a) Rules and Restrictions of Operator Overloading [4]
Rules:
- Operator overloading is done by defining a function whose name is
operatorfollowed by the symbol, e.g.operator+. - At least one operand must be a user-defined type (you cannot redefine operators for built-in types only).
- The number of operands, precedence and associativity of an operator cannot be changed.
- You cannot create new operators (e.g.
**). - Operators can be overloaded as member functions or friend (non-member) functions. Unary operators take no argument (member) or one argument (friend); binary operators take one argument (member) or two (friend).
=,[],(),->must be overloaded only as member functions.
Operators that CANNOT be overloaded and why:
| Operator | Reason |
|---|---|
. (member access) | Must keep its standard meaning for all members |
.* (pointer-to-member) | Same reason |
:: (scope resolution) | Operates on names at compile time, not values |
?: (ternary conditional) | Evaluation/control-flow semantics cannot be expressed as a function |
sizeof | Resolved by the compiler |
(b) Complex class overloading + and * (one via friend) [8]
#include <iostream>
using namespace std;
class Complex {
double re, im;
public:
Complex(double r = 0, double i = 0) : re(r), im(i) {}
// '+' overloaded as a friend function
friend Complex operator+(const Complex &a, const Complex &b);
// '*' overloaded as a member function
Complex operator*(const Complex &b) const {
return Complex(re * b.re - im * b.im, // (a+bi)(c+di)
re * b.im + im * b.re);
}
void display() const {
cout << re << (im >= 0 ? " + " : " - ")
<< (im >= 0 ? im : -im) << "i" << endl;
}
};
Complex operator+(const Complex &a, const Complex &b) {
return Complex(a.re + b.re, a.im + b.im);
}
int main() {
Complex c1(3, 2), c2(1, 4);
Complex sum = c1 + c2; // calls friend operator+
Complex prod = c1 * c2; // calls member operator*
cout << "Sum = "; sum.display();
cout << "Product = "; prod.display();
return 0;
}
Output:
Sum = 4 + 6i
Product = -5 + 14i
(Check: ; .)
(a) Explain the exception handling mechanism in C++ using try, catch, and throw. How can multiple catch blocks be used to handle different types of exceptions? [6]
(b) Write a C++ program that reads integers from a file named data.txt, computes their sum, and writes the result to result.txt. The program must throw and handle an exception if the input file cannot be opened. [6]
(a) Exception Handling in C++ [6]
C++ handles run-time errors using three keywords:
try– encloses the block of code that may raise an exception.throw– signals (raises) an exception when an error is detected, passing an exception object/value.catch– immediately follows atryblock and handles an exception of a matching type.
Mechanism: When throw executes, normal flow stops, the stack is unwound (local objects destroyed), and control transfers to the nearest matching catch. If no handler matches, std::terminate() is called.
try {
if (b == 0) throw "Division by zero"; // raise
cout << a / b;
}
catch (const char* msg) { // handle
cout << "Error: " << msg;
}
Multiple catch blocks: A single try can be followed by several catch blocks, each handling a different exception type. They are tested top-to-bottom; the first one whose type matches the thrown object is executed. A general handler catch(...) is placed last to catch any remaining type.
try { /* ... */ }
catch (int e) { cout << "int exception"; }
catch (double e) { cout << "double exception"; }
catch (const char* e) { cout << "string exception"; }
catch (...) { cout << "any other exception"; }
(b) File sum program with exception on open failure [6]
#include <iostream>
#include <fstream>
#include <stdexcept>
using namespace std;
int main() {
try {
ifstream fin("data.txt");
if (!fin) // open failed
throw runtime_error("Cannot open input file data.txt");
int x, sum = 0;
while (fin >> x) sum += x; // read integers
fin.close();
ofstream fout("result.txt");
if (!fout)
throw runtime_error("Cannot open output file result.txt");
fout << "Sum = " << sum << endl; // write result
fout.close();
cout << "Sum (" << sum << ") written to result.txt" << endl;
}
catch (const exception &e) {
cout << "Exception: " << e.what() << endl; // handle
}
return 0;
}
If data.txt exists with 10 20 30, then result.txt contains Sum = 60. If the file is missing, the program prints Exception: Cannot open input file data.txt.
Section B: Short Answer Questions
Attempt all / any as specified.
Differentiate between a constructor and a destructor. Explain the concept of a copy constructor with an example and state when the default copy constructor leads to problems (shallow copy).
Constructor vs Destructor; Copy Constructor; Shallow Copy [6]
Constructor vs Destructor:
| Constructor | Destructor |
|---|---|
| Same name as class | Same name preceded by ~ |
| Called automatically when an object is created | Called automatically when an object is destroyed/goes out of scope |
| Can take arguments and be overloaded | Takes no arguments, cannot be overloaded (only one per class) |
| Initializes data members / allocates resources | Releases resources (frees memory, closes files) |
Copy Constructor: A special constructor that creates a new object as a copy of an existing object of the same class. Signature: ClassName(const ClassName &obj);. It is invoked when an object is initialized from another, passed by value, or returned by value.
class Array {
int *p; int n;
public:
Array(int n): n(n) { p = new int[n]; }
// Deep copy constructor
Array(const Array &a): n(a.n) {
p = new int[n];
for (int i = 0; i < n; i++) p[i] = a.p[i];
}
~Array() { delete[] p; }
};
Problem with default copy constructor (shallow copy): When a class manages a pointer/dynamic resource, the compiler-generated default copy constructor simply copies the pointer value, so both objects point to the same memory. This causes:
- Aliasing – changing one object affects the other.
- Double free / dangling pointer – when both destructors run, the same memory is
deleted twice, causing a crash.
The remedy is to write a user-defined (deep) copy constructor (and assignment operator) that allocates fresh memory and copies the contents, as shown above.
Explain the different types of inheritance supported in C++ with neat diagrams. Discuss the ambiguity problem that arises in multiple inheritance and how it is resolved using virtual base classes.
Types of Inheritance and the Diamond Problem [6]
Inheritance lets a derived class reuse and extend a base class. C++ supports five forms:
- Single inheritance – one base, one derived.
A | B - Multilevel inheritance – a chain; B derives from A, C derives from B.
A -> B -> C - Multiple inheritance – one derived class with several bases.
A B \ / C - Hierarchical inheritance – many derived classes from one base.
A / \ B C - Hybrid inheritance – combination of the above (often produces the diamond shape below).
Ambiguity in Multiple Inheritance (Diamond Problem)
Consider:
A
/ \
B C (B and C inherit from A)
\ /
D (D inherits from both B and C)
If class A has a member x, then through normal multiple inheritance D receives two copies of A (one via B, one via C). A reference to d.x becomes ambiguous — the compiler cannot decide which copy is meant — producing a compile error.
Resolution using Virtual Base Class
Declaring A as a virtual base class when B and C derive from it ensures that only one shared copy of A is inherited by D, removing the ambiguity.
class A { public: int x; };
class B : virtual public A { };
class C : virtual public A { };
class D : public B, public C { }; // single copy of A
int main() {
D d;
d.x = 10; // unambiguous now
}
The keyword virtual in the inheritance list makes A a virtual base, so D contains exactly one A sub-object.
What are function templates and class templates? Write a function template maximum() that returns the largest of two values of any data type, and show how it is invoked for int and double arguments.
Function Templates and Class Templates [6]
Function template: A single function definition that works for any data type. The compiler generates a concrete function for each type used (generic programming). Declared with template <class T>.
Class template: A blueprint for a family of classes parameterized by a type, e.g. a Stack<T> or Array<T> that can hold any element type. Declared with template <class T> before the class.
maximum() function template:
#include <iostream>
using namespace std;
template <class T>
T maximum(T a, T b) {
return (a > b) ? a : b;
}
int main() {
cout << maximum(10, 25) << endl; // T = int -> 25
cout << maximum(3.7, 2.9) << endl; // T = double -> 3.7
return 0;
}
Output:
25
3.7
When called with int arguments the compiler instantiates maximum<int>; with double arguments it instantiates maximum<double> — one template, multiple type-specific versions.
What is a pure virtual function? Define an abstract base class with an example and explain why an object of an abstract class cannot be instantiated.
Pure Virtual Function and Abstract Base Class [6]
Pure virtual function: A virtual function that has no definition in the base class and is declared by assigning 0:
virtual void draw() = 0; // pure virtual
It provides only an interface (declaration) that every concrete derived class must override.
Abstract base class: A class that contains at least one pure virtual function. It is meant to serve as a common interface/base for derived classes and cannot itself be instantiated.
class Shape { // abstract base class
public:
virtual double area() = 0; // pure virtual
virtual ~Shape() {}
};
class Circle : public Shape {
double r;
public:
Circle(double r): r(r) {}
double area() override { return 3.14159 * r * r; } // must override
};
Why an object of an abstract class cannot be instantiated: Because a pure virtual function has no body, an abstract class is incomplete — it has at least one operation with no implementation. Creating an object would leave that function undefined, so the compiler forbids it (Shape s; is an error). However, you can declare a pointer or reference of the abstract type (Shape *p = new Circle(5);) and use it for run-time polymorphism. A derived class becomes concrete (instantiable) only after it overrides all inherited pure virtual functions.
Explain the difference between text mode and binary mode file handling in C++. Describe the use of the file pointers and the functions seekg(), seekp(), and tellg() for random access in files.
Text vs Binary Mode and Random Access in Files [6]
Text mode vs Binary mode:
| Text mode | Binary mode |
|---|---|
| Data stored as human-readable characters | Data stored as raw bytes exactly as in memory |
Numbers converted to/from their character representation (e.g. 123 -> '1','2','3') | No conversion; bit pattern written directly |
May translate newlines (\n <-> \r\n on some systems) | No newline/character translation |
Used with <<, >> operators | Used with read() / write(); opened with ios::binary |
| Larger/slower for numeric data | Compact and exact, ideal for structures |
File pointers: Every file stream maintains two position markers:
- get pointer – the position from which the next read occurs.
- put pointer – the position at which the next write occurs.
These let us perform random access (jump to any byte) instead of only sequential access:
| Function | Purpose |
|---|---|
seekg(pos) / seekg(off, dir) | Move the get pointer to an absolute or relative position |
seekp(pos) / seekp(off, dir) | Move the put pointer |
tellg() | Return current position of the get pointer |
tellp() | Return current position of the put pointer |
The direction dir can be ios::beg (from start), ios::cur (from current), or ios::end (from end).
fin.seekg(0, ios::end); // go to end
int size = fin.tellg(); // size = number of bytes in file
fin.seekg(10, ios::beg); // jump to the 11th byte to read
Thus seekg/seekp reposition for reading/writing and tellg/tellp report the current offset, enabling efficient random access (e.g. updating one record in the middle of a file).
Explain the meaning of static data members and static member functions of a class. Write a short program that uses a static data member to count the number of objects created from a class.
Static Data Members and Static Member Functions [6]
Static data member: A class variable declared with static. There is exactly one copy shared by all objects of the class (it belongs to the class, not to any individual object). It exists even when no object has been created and must be defined once outside the class.
Static member function: A function declared with static. It can be called using the class name (ClassName::func()) without any object, but it can access only static members because it has no this pointer.
Program – counting objects with a static data member:
#include <iostream>
using namespace std;
class Counter {
static int count; // shared by all objects
public:
Counter() { count++; } // increment on creation
~Counter() { count--; } // decrement on destruction
static int getCount() { return count; } // static member function
};
int Counter::count = 0; // definition of static member
int main() {
Counter a, b;
cout << "Objects = " << Counter::getCount() << endl; // 2
{
Counter c;
cout << "Objects = " << Counter::getCount() << endl; // 3
} // c destroyed here
cout << "Objects = " << Counter::getCount() << endl; // 2
return 0;
}
Output:
Objects = 2
Objects = 3
Objects = 2
Because count is static, every constructor/destructor updates the same variable, giving a live count of existing objects.
Distinguish between overloading a unary operator using a member function and using a friend function. Write a program segment to overload the unary ++ operator (prefix form) for a Counter class.
Unary Operator Overloading: Member vs Friend; Prefix ++ for Counter [6]
Member function vs Friend function (unary operator):
| Member function | Friend function |
|---|---|
Takes no explicit argument; the operand is the calling object (this) | Takes one explicit argument (the operand object) |
Invoked as obj.operator++() | Invoked as operator++(obj) |
Has access to members via this | Declared friend; accesses private members directly through the argument |
| Used when the left operand must be an object of the class | Useful when the operand may be a non-class type or for symmetry |
Overloading prefix ++ for a Counter class (member function form):
#include <iostream>
using namespace std;
class Counter {
int value;
public:
Counter(int v = 0) : value(v) {}
// Prefix ++ : no argument, returns reference to the modified object
Counter& operator++() {
++value;
return *this;
}
void show() { cout << "Value = " << value << endl; }
};
int main() {
Counter c(5);
++c; // calls operator++()
c.show(); // Value = 6
return 0;
}
(For the friend form the signature would be friend Counter& operator++(Counter &c);.) The empty parameter list distinguishes the prefix form; an int dummy parameter operator++(int) would denote the postfix form.
Write short notes on: (a) the catch(...) block (catch-all handler), and (b) rethrowing an exception.
Short Notes [4]
(a) The catch(...) block (catch-all handler) [2]
The handler catch(...) uses an ellipsis as its parameter and matches an exception of any type. It is used as a last resort when the exact exception type is unknown, ensuring no exception escapes unhandled. It must be placed last among the catch blocks for a try, because once written, no catch after it would ever be reached.
try { /* code */ }
catch (int e) { /* handle int */ }
catch (...) { cout << "Unknown exception caught"; } // catch-all
Limitation: it cannot access the value/type of the thrown object.
(b) Rethrowing an exception [2]
Inside a catch block, writing throw; (with no operand) rethrows the currently handled exception, passing it up to an outer try/catch. This lets a function do partial handling (e.g. logging or cleanup) and then propagate the same exception to a higher level for further handling.
try {
try { throw runtime_error("error"); }
catch (...) {
cout << "Logging, then rethrowing\n";
throw; // rethrow to outer handler
}
}
catch (const exception &e) {
cout << "Outer caught: " << e.what();
}
Frequently asked questions
- Where can I find the BE Computer Engineering (IOE, TU) Object Oriented Programming (IOE, CT 501) question paper 2078?
- The full BE Computer Engineering (IOE, TU) Object Oriented Programming (IOE, CT 501) 2078 (regular) question paper is available free on Kekkei. You can read every question online and attempt the paper under timed exam conditions.
- Does the Object Oriented Programming (IOE, CT 501) 2078 paper come with solutions?
- Yes. Every question on this Object Oriented Programming (IOE, CT 501) past paper includes a step-by-step solution, plus instant AI feedback when you attempt it on Kekkei.
- How many marks is the BE Computer Engineering (IOE, TU) Object Oriented Programming (IOE, CT 501) 2078 paper?
- The BE Computer Engineering (IOE, TU) Object Oriented Programming (IOE, CT 501) 2078 paper carries 80 full marks and is meant to be completed in 180 minutes, across 12 questions.
- Is practising this Object Oriented Programming (IOE, CT 501) past paper free?
- Yes — reading and attempting this Object Oriented Programming (IOE, CT 501) past paper on Kekkei is completely free.