BIT153 · TU past paper
Object Oriented Programming 2080 question paper
The complete TU 2080 exam paper for Object Oriented Programming (BIT153), all 12 questions with solved model answers written to the mark scheme.
Tap a question to open its answer.
- 110 marksConstructor definition and purposeHideAnswer
What is constructor? Explain its types with suitable example.How is the constructor called in a derived class in C++?[6+4]
Constructor in C++
What is a Constructor?
A constructor is a special member function of a class that is automatically called when an object of that class is created. It is used to initialize the data members of the class.
Key Characteristics:
- Has the same name as the class
- Has no return type (not even
void) - Called automatically when an object is created
- Can be overloaded
Types of Constructors
1. Default Constructor
A constructor that takes no arguments. If no constructor is defined, the compiler provides one automatically.
#include<iostream> using namespace std; class Student { int roll; string name; public: // Default Constructor Student() { roll = 0; name = "Unknown"; cout << "Default Constructor called" << endl; } void display() { cout << "Roll: " << roll << ", Name: " << name << endl; } }; int main() { Student s1; // Default constructor called automatically s1.display(); return 0; }Output:
Default Constructor called Roll: 0, Name: Unknown
2. Parameterized Constructor
A constructor that accepts one or more arguments to initialize objects with specific values.
#include<iostream> using namespace std; class Student { int roll; string name; public: // Parameterized Constructor Student(int r, string n) { roll = r; name = n; cout << "Parameterized Constructor called" << endl; } void display() { cout << "Roll: " << roll << ", Name: " << name << endl; } }; int main() { Student s1(101, "Ram"); // Parameterized constructor called s1.display(); return 0; }Output:
Parameterized Constructor called Roll: 101, Name: Ram
3. Copy Constructor
A constructor that creates a new object as a copy of an existing object. It takes a reference to an object of the same class as its argument.
#include<iostream> using namespace std; class Student { int roll; string name; public: Student(int r, string n) { roll = r; name = n; } // Copy Constructor Student(const Student &s) { roll = s.roll; name = s.name; cout << "Copy Constructor called" << endl; } void display() { cout << "Roll: " << roll << ", Name: " << name << endl; } }; int main() { Student s1(101, "Ram"); Student s2(s1); // Copy constructor called s2.display(); return 0; }Output:
Copy Constructor called Roll: 101, Name: Ram
4. Constructor Overloading
Multiple constructors with different parameter lists in the same class.
#include<iostream> using namespace std; class Rectangle { float length, breadth; public: Rectangle() { // Default length = breadth = 0; } Rectangle(float l, float b) { // Parameterized length = l; breadth = b; } void area() { cout << "Area = " << length * breadth << endl; } }; int main() { Rectangle r1; // calls default constructor Rectangle r2(5.0, 3.0); // calls parameterized constructor r1.area(); r2.area(); return 0; }
Calling Constructor in a Derived Class
When a derived class object is created, both the base class constructor and the derived class constructor are called. The base class constructor is called first, then the derived class constructor.
To explicitly pass arguments to the base class constructor, we use an initializer list with the colon (
:) syntax.Syntax:
DerivedClass(parameters) : BaseClass(arguments) { // derived class constructor body }Order of Execution:
- Base class constructor executes first
- Derived class constructor executes next
Example:
#include<iostream> using namespace std; // Base Class class Animal { string name; public: Animal(string n) { name = n; cout << "Animal Constructor: " << name << endl; } }; // Derived Class class Dog : public Animal { string breed; public: // Calling base class constructor using initializer list Dog(string n, string b) : Animal(n) { breed = b; cout << "Dog Constructor: Breed = " << breed << endl; } }; int main() { Dog d1("Tommy", "Labrador"); return 0; }Output:
Animal Constructor: Tommy Dog Constructor: Breed = LabradorKey Points:
Aspect Detail Base constructor call Always called before derived constructor Syntax Derived(params) : Base(args) { }Default base constructor Called automatically if not specified Destructor order Reverse of constructor order Note: If the base class has only a parameterized constructor (no default constructor), the derived class must explicitly call it using the initializer list, otherwise a compile-time error occurs.
- 210 marksVirtual functionsHideAnswer
What is Polymorphism in Object Oriented Programming? Implement a class Employee with a virtual function CalculateSalary() that returns the salary of the employee. Create two derived classes HourlyEmployee and SalariedEmployee. Override the CalculateSalary() function in both derived classes to calculate the salary of an hourly employee and a salaried employee respectively. Write a program that creates objects of both derived classes and calls the CalculateSalary() function for each.[10]
Polymorphism in OOP and Virtual Function Implementation
What is Polymorphism?
Polymorphism is one of the four fundamental pillars of Object Oriented Programming (along with Encapsulation, Inheritance, and Abstraction). The word polymorphism comes from Greek meaning "many forms".
In OOP, polymorphism means the ability of a single interface (function name or operator) to behave differently depending on the object that invokes it.
Types of Polymorphism
Type Also Known As Resolved At Compile-time Polymorphism Static / Early Binding Compile time Run-time Polymorphism Dynamic / Late Binding Run time - Compile-time polymorphism is achieved through function overloading and operator overloading.
- Run-time polymorphism is achieved through virtual functions and function overriding (inheritance).
Key Concepts for Run-time Polymorphism
- Virtual Function: A function declared with the keyword
virtualin the base class. It tells the compiler to resolve the function call at run time based on the actual object type, not the pointer/reference type. - Override: Redefining a virtual function in a derived class with the same signature.
- Base class pointer can point to derived class objects, and the correct overridden function is called automatically (dynamic dispatch).
C++ Program Implementation
#include <iostream> using namespace std; // ----------------------------------------------- // Base Class: Employee // ----------------------------------------------- class Employee { protected: string name; public: // Constructor Employee(string empName) { name = empName; } // Virtual function to be overridden in derived classes virtual double CalculateSalary() { return 0.0; } // Virtual display function virtual void display() { cout << "Employee Name : " << name << endl; cout << "Salary : Rs. " << CalculateSalary() << endl; } // Virtual destructor (good practice with virtual functions) virtual ~Employee() {} }; // ----------------------------------------------- // Derived Class 1: HourlyEmployee // Salary = hoursWorked * hourlyRate // ----------------------------------------------- class HourlyEmployee : public Employee { private: double hoursWorked; double hourlyRate; public: // Constructor HourlyEmployee(string empName, double hours, double rate) : Employee(empName) { hoursWorked = hours; hourlyRate = rate; } // Override CalculateSalary() double CalculateSalary() override { return hoursWorked * hourlyRate; } void display() override { cout << "----- Hourly Employee -----" << endl; cout << "Employee Name : " << name << endl; cout << "Hours Worked : " << hoursWorked << endl; cout << "Hourly Rate : Rs. " << hourlyRate << endl; cout << "Total Salary : Rs. " << CalculateSalary() << endl; } }; // ----------------------------------------------- // Derived Class 2: SalariedEmployee // Salary = fixedMonthlySalary (fixed, no calculation needed) // ----------------------------------------------- class SalariedEmployee : public Employee { private: double monthlySalary; public: // Constructor SalariedEmployee(string empName, double salary) : Employee(empName) { monthlySalary = salary; } // Override CalculateSalary() double CalculateSalary() override { return monthlySalary; } void display() override { cout << "----- Salaried Employee -----" << endl; cout << "Employee Name : " << name << endl; cout << "Monthly Salary : Rs. " << CalculateSalary() << endl; } }; // ----------------------------------------------- // Main Function // ----------------------------------------------- int main() { // Create objects of derived classes HourlyEmployee emp1("Ram Sharma", 160, 150.0); // 160 hrs, Rs.150/hr SalariedEmployee emp2("Sita Thapa", 55000.0); // Fixed Rs.55000/month // Call display (which internally calls CalculateSalary) emp1.display(); cout << endl; emp2.display(); cout << endl; // Demonstrating Run-time Polymorphism using Base class pointer cout << "=== Run-time Polymorphism Demo ===" << endl; Employee* empPtr; // Base class pointer empPtr = &emp1; // Points to HourlyEmployee object cout << "Salary (via base pointer): Rs. " << empPtr->CalculateSalary() << endl; empPtr = &emp2; // Points to SalariedEmployee object cout << "Salary (via base pointer): Rs. " << empPtr->CalculateSalary() << endl; return 0; }
Expected Output
----- Hourly Employee ----- Employee Name : Ram Sharma Hours Worked : 160 Hourly Rate : Rs. 150 Total Salary : Rs. 24000 ----- Salaried Employee ----- Employee Name : Sita Thapa Monthly Salary : Rs. 55000 === Run-time Polymorphism Demo === Salary (via base pointer): Rs. 24000 Salary (via base pointer): Rs. 55000
Explanation of Key Points
Concept Where Used virtualkeywordDeclared in Employee::CalculateSalary()overridekeywordUsed in both derived classes (C++11) Dynamic Dispatch Base class pointer empPtrcalls correct version at run time - 310 marksOperator overloading definition and purposHideAnswer
What is operator overloading? Write a complete C++ program to overload + operator to add two objects of class 'Time'.[10]
Operator overloading is a feature of C++ that allows the programmer to redefine or extend the meaning of existing operators (such as +, -, , ==, etc.) for user-defined data types (classes and structures). It enables objects of a class to...
- 45 marksPublic, private, and protected inheritanceHideAnswer
What is the difference between public, private and protected inheritance in C++? [5]
In C++, when a derived class inherits from a base class, an access specifier is used to control how the inherited members are accessible in the derived class and further down the hierarchy. Syntax: --- The inherited member's accessibilit...
- 55 marksException handling definition and purposeHideAnswer
What is exception handling? Explain types of exception handling and explain with suitable example. [5]
Exception Handling in C++
What exception handling is
Exception handling is the mechanism by which a C++ program reports a fault at the point where it is detected and deals with it at the point where there is enough context to decide what to do. The detecting code executes
throw, which creates an exception object; the runtime then searches outward through the enclosingtryblocks for acatchhandler whose type matches, destroying every local object it passes on the way. That destruction, called stack unwinding, is what makes the mechanism safe.The result is a clean split: the ordinary logic stays in the
tryblock and the recovery logic sits in the handlers, instead of an error test being wedged in after every call.The constructs C++ provides
Construct Purpose tryEncloses code whose exceptions are to be handled catchHandles one type of exception; several may follow one trythrowRaises an exception, or rethrows the current one when written bare catch (...)Catches an exception of any type at all noexceptPromises a function throws nothing, so the compiler may optimise accordingly There is deliberately no
finallyin this list. C++ does not have one, because cleanup belongs in the destructor of the object that owns the resource, and destructors are run automatically during unwinding.The standard exception hierarchy
Most thrown types derive from
std::exception, declared in<exception>, which offers the single memberwhat()returning a description. Two broad families sit under it, in<stdexcept>:- Logic errors, faults a correct program should have prevented:
std::logic_error, and under itstd::invalid_argument,std::out_of_range,std::domain_error,std::length_error. - Runtime errors, faults only detectable while running:
std::runtime_error, and under itstd::overflow_error,std::underflow_error,std::range_error.
std::bad_allocfrom a failednewandstd::bad_castfrom a faileddynamic_caston a reference also derive fromstd::exception. Because they share a base, one handler forconst std::exception&can catch the whole family.Forms exception handling takes
A single try with one handler
#include <iostream> #include <stdexcept> int divide(int a, int b) { if (b == 0) throw std::runtime_error("division by zero"); // C++ does not throw here by itself return a / b; } int main() { try { std::cout << divide(10, 0) << "\n"; } catch (const std::runtime_error& e) { std::cout << "Error: " << e.what() << "\n"; } }Integer division by zero is undefined behaviour in C++, not an automatic exception, so the divisor is tested and the exception thrown on purpose. Anyone coming from Java should note that there is no
ArithmeticExceptionhere to rely on.Several handlers on one try
Handlers are tried in order and the first matching one wins, so the most derived type must be written first. A base class handler placed above a derived one would swallow it.
#include <iostream> #include <vector> #include <stdexcept> int main() { std::vector<int> v{10, 20, 30, 40, 50}; try { std::cout << v.at(2) << "\n"; // fine std::cout << v.at(10) << "\n"; // at() checks the index and throws } catch (const std::out_of_range& e) { // most derived first std::cout << "Index error: " << e.what() << "\n"; } catch (const std::exception& e) { // then the general case std::cout << "Other error: " << e.what() << "\n"; } catch (...) { // anything not derived from std::exception std::cout << "Unknown error\n"; } }A raw array subscript is not checked by C++ and throws nothing, so
v[10]on a plain array would simply corrupt memory.std::vector::at()performs the bounds test and throwsstd::out_of_range, which is why it is used here.Throwing an exception of your own
Deriving from
std::runtime_errorcosts one line and gives the new type a workingwhat().#include <iostream> #include <stdexcept> #include <string> class NotEligible : public std::runtime_error { public: explicit NotEligible(const std::string& msg) : std::runtime_error(msg) {} }; void checkAge(int age) { if (age < 18) throw NotEligible("not eligible to vote"); std::cout << "Eligible to vote\n"; } int main() { try { checkAge(15); } catch (const NotEligible& e) { std::cout << "Caught: " << e.what() << "\n"; } }Output:
Caught: not eligible to voteCleanup, which is where RAII replaces finally
#include <iostream> #include <fstream> #include <stdexcept> #include <string> class LogFile { std::ofstream out; public: explicit LogFile(const std::string& name) : out(name) { std::cout << "Log opened\n"; } ~LogFile() { std::cout << "Log closed\n"; } // runs even while an exception propagates void write(const std::string& s) { out << s << "\n"; } }; int main() { try { LogFile log("run.txt"); log.write("working"); throw std::runtime_error("something failed"); } catch (const std::exception& e) { std::cout << "Error: " << e.what() << "\n"; } std::cout << "Program continues\n"; }Output:
Log opened Log closed Error: something failed Program continuesThe destructor of
logruns during unwinding, before the handler body, so the resource is released with no cleanup code written at the call site. Astd::unique_ptror astd::lock_guardgives the same guarantee for heap memory and for mutexes.Points of practice
Catch by
constreference, never by value, since catching a base class by value slices away the derived part of the exception object. Order handlers from most derived to most general. Never let an exception escape a destructor, because unwinding while another exception is active callsstd::terminate. Throw only for genuinely exceptional conditions, and use a return value orstd::optionalfor outcomes that are expected.Taken together,
try,catch,throw, and the destructors that run during unwinding give C++ a complete error handling mechanism: the fault is reported where it is seen, handled where it can be dealt with, and every resource acquired in between is released on the way out. - Logic errors, faults a correct program should have prevented:
- 65 marksFriend functionsHideAnswer
What is friend function? Write a program to add private member of two different classes using friend function. [5]
A friend function is a function that is not a member of a class but has access to the private and protected members of that class. It is declared inside the class using the keyword friend, but it is defined outside the class like a norma...
- 75 marksReturning objects from functionsHideAnswer
Write a program to demonstrate returning object from functions in C++. [5]
In C++, a function can return an object of a class just like it returns any other data type. The returned object is a copy of the local object created inside the function. Point Explanation -------------------- Return type The return typ...
- 85 marksThis pointer for name conflict resolutionHideAnswer
How 'this' pointer is used to resolve name conflict between local variable and member variable in C++? Explain with example. [5]
The this pointer is an implicit pointer available inside every non-static member function of a class. It automatically holds the address of the object that called the member function. Its type is ClassName. --- A name conflict arises whe...
- 95 marksFile handling with objectsHideAnswer
Write a Program to read and write values through object using File Handling. [5]
File handling in C++ allows storing and retrieving object data (attributes) to/from files using fstream. We use write() to store binary data and read() to retrieve it. --- --- --- Feature Description ------ fstream Used for both reading ...
- 105 marksClass templatesHideAnswer
What do you mean by class template in C++? Write a program in C++ containing function template which determines the greater number between two integer inputs and two floating point inputs. [5]
A class template in C++ is a blueprint for creating a family of classes where the data type is parameterized. Instead of writing separate classes for different data types, a single class template can be defined and the compiler generates...
- 115 marksFunction overridingHideAnswer
Differentiate between function overloading and function overriding in C++. [5]
--- Function overloading means defining multiple functions with the same name but with different parameter lists (different number, type, or order of parameters) within the same class or scope. - Resolved at compile time (Static/Early Bi...
- 125 marksStatic data members and static functionsHideAnswer
Illustrate the use of static variable with a simple program. [5]
A static variable is a variable that retains its value between function calls. It is initialized only once (at the first call) and exists for the entire lifetime of the program, even though its scope may be local to a function. --- Prope...