Browse papers
A

Section A: Long Answer Questions

Attempt all / any as specified.

4 questions
1long12 marks

(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 membersMember functions
Variables declared inside a class that hold the object's stateFunctions declared inside a class that operate on the data members
Represent attributesRepresent 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.

classes-and-objectsconstructors-and-destructors
2long12 marks

(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:

  1. A base-class pointer (or reference) is made to point to a derived-class object: Base *p = &derivedObj;.
  2. The base class declares the function virtual.
  3. 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.
  4. 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.

inheritancepolymorphism-and-virtual-functions
3long12 marks

(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 operator followed 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:

OperatorReason
. (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
sizeofResolved 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: (3+2i)+(1+4i)=4+6i(3+2i)+(1+4i)=4+6i; (3+2i)(1+4i)=3+12i+2i+8i2=5+14i(3+2i)(1+4i)=3+12i+2i+8i^2=-5+14i.)

operator-overloadingtemplates
4long12 marks

(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 a try block 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.

exception-handlingfile-streams
B

Section B: Short Answer Questions

Attempt all / any as specified.

8 questions
5short6 marks

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:

ConstructorDestructor
Same name as classSame name preceded by ~
Called automatically when an object is createdCalled automatically when an object is destroyed/goes out of scope
Can take arguments and be overloadedTakes no arguments, cannot be overloaded (only one per class)
Initializes data members / allocates resourcesReleases 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.

constructors-and-destructors
6short6 marks

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:

  1. Single inheritance – one base, one derived.
    A
    |
    B
    
  2. Multilevel inheritance – a chain; B derives from A, C derives from B.
    A -> B -> C
    
  3. Multiple inheritance – one derived class with several bases.
    A   B
     \ /
      C
    
  4. Hierarchical inheritance – many derived classes from one base.
       A
      / \
     B   C
    
  5. 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.

inheritance
7short6 marks

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.

templates
8short6 marks

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.

polymorphism-and-virtual-functions
9short6 marks

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 modeBinary mode
Data stored as human-readable charactersData 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 <<, >> operatorsUsed with read() / write(); opened with ios::binary
Larger/slower for numeric dataCompact 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:

FunctionPurpose
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).

file-streams
10short6 marks

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.

classes-and-objects
11short6 marks

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 functionFriend 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 thisDeclared friend; accesses private members directly through the argument
Used when the left operand must be an object of the classUseful 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.

operator-overloadingclasses-and-objects
12short4 marks

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();
}
exception-handling

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.