BSc CSIT (TU) Science Object-Oriented Programming (BSc CSIT, CSC161) Question Paper 2079 Nepal
This is the official BSc CSIT (TU) (Science stream) Object-Oriented Programming (BSc CSIT, CSC161) question paper for 2079, as set in the regular annual examination. It carries 60 full marks and a time allowance of 180 minutes, across 12 questions. On Kekkei you can attempt this Object-Oriented Programming (BSc CSIT, CSC161) 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 BSc CSIT (TU) Object-Oriented Programming (BSc CSIT, CSC161) exam or solving previous years' question papers, this 2079 paper is a great way to practise under real exam conditions.
Section A: Long Answer Questions
Attempt any TWO questions.
What is polymorphism? Differentiate between compile-time and run-time polymorphism. Explain with examples how each is achieved in C++.
Polymorphism
Polymorphism ("many forms") is an OOP feature that lets a single interface, function name, or operator behave differently depending on the type of object or the arguments involved. It allows the same message to be interpreted in different ways.
Compile-time vs Run-time Polymorphism
| Feature | Compile-time (Static) | Run-time (Dynamic) |
|---|---|---|
| Binding | Early/static binding (resolved at compile time) | Late/dynamic binding (resolved at run time) |
| Achieved by | Function overloading, operator overloading | Virtual functions + inheritance |
| Speed | Faster (no run-time lookup) | Slower (uses vtable lookup) |
| Flexibility | Less flexible | More flexible (extensible) |
| Mechanism | Function signature / number/type of args | Base-class pointer/reference to derived object |
Compile-time Polymorphism (Function Overloading)
The compiler selects the correct function from several with the same name based on the argument list.
class Print {
public:
void show(int x) { cout << "int: " << x << endl; }
void show(double x) { cout << "double: " << x << endl; }
void show(string x) { cout << "string: " << x << endl; }
};
int main() {
Print p;
p.show(5); // calls show(int)
p.show(3.14); // calls show(double)
p.show("hi"); // calls show(string)
}
Run-time Polymorphism (Virtual Functions)
A base-class pointer/reference calls the overridden function of the actual derived object, decided at run time.
class Animal {
public:
virtual void sound() { cout << "Some sound" << endl; }
};
class Dog : public Animal {
public:
void sound() override { cout << "Bark" << endl; }
};
class Cat : public Animal {
public:
void sound() override { cout << "Meow" << endl; }
};
int main() {
Animal* a;
Dog d; Cat c;
a = &d; a->sound(); // Bark (resolved at run time)
a = &c; a->sound(); // Meow
}
Without virtual, a->sound() would always call the base version (static binding). The virtual keyword enables dynamic dispatch through the vtable.
Explain the concept of an abstract class and pure virtual function. Write a C++ program to demonstrate an abstract base class 'Shape' with derived classes.
Abstract Class and Pure Virtual Function
A pure virtual function is a virtual function with no definition in the base class, declared by assigning = 0:
virtual double area() = 0;
It forces every concrete derived class to provide its own implementation.
An abstract class is a class that contains at least one pure virtual function. It cannot be instantiated (no objects can be created from it); it only serves as a base/interface to be inherited. A pointer or reference to an abstract class is allowed and is used to achieve run-time polymorphism.
C++ Program: Abstract Base Class Shape
#include <iostream>
using namespace std;
class Shape { // abstract base class
protected:
double d1, d2;
public:
Shape(double a = 0, double b = 0) : d1(a), d2(b) {}
virtual double area() = 0; // pure virtual function
virtual void show() { // ordinary virtual function
cout << "Area = " << area() << endl;
}
virtual ~Shape() {}
};
class Circle : public Shape {
public:
Circle(double r) : Shape(r) {}
double area() override { return 3.14159 * d1 * d1; }
};
class Rectangle : public Shape {
public:
Rectangle(double l, double b) : Shape(l, b) {}
double area() override { return d1 * d2; }
};
class Triangle : public Shape {
public:
Triangle(double b, double h) : Shape(b, h) {}
double area() override { return 0.5 * d1 * d2; }
};
int main() {
Shape* shapes[3];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
shapes[2] = new Triangle(3, 8);
for (int i = 0; i < 3; i++) shapes[i]->show(); // polymorphic call
for (int i = 0; i < 3; i++) delete shapes[i];
return 0;
}
Output:
Area = 78.5397
Area = 24
Area = 12
Here Shape cannot be instantiated; the base pointer array calls each derived area() through dynamic binding, demonstrating run-time polymorphism.
What is operator overloading? Write a C++ program to overload the unary '++' operator (both prefix and postfix) for a Counter class.
Operator Overloading
Operator overloading lets you redefine the meaning of a built-in C++ operator (such as +, ==, ++) for user-defined types (classes), so that objects can be manipulated with natural operator syntax. It is a form of compile-time (static) polymorphism and is implemented using the keyword operator followed by the operator symbol.
For the unary ++ operator:
- Prefix
++objis overloaded asoperator++()(no parameter). - Postfix
obj++is overloaded asoperator++(int)— the dummyintparameter distinguishes it from the prefix form.
C++ Program: Overloading Unary ++ for a Counter Class
#include <iostream>
using namespace std;
class Counter {
int count;
public:
Counter(int c = 0) : count(c) {}
// Prefix: ++c
Counter operator++() {
++count;
return *this;
}
// Postfix: c++ (dummy int parameter)
Counter operator++(int) {
Counter temp = *this; // save old value
count++;
return temp; // return old value
}
void display() { cout << "Count = " << count << endl; }
};
int main() {
Counter c(5);
++c; // prefix
c.display(); // Count = 6
c++; // postfix
c.display(); // Count = 7
Counter a = c++; // postfix returns old value
a.display(); // Count = 7 (old)
c.display(); // Count = 8 (new)
return 0;
}
Key point: the postfix version returns the previous state (using a temporary), while the prefix version increments first and returns the updated object.
Section B: Short Answer Questions
Attempt any EIGHT questions.
What is abstraction? Differentiate it from encapsulation.
Abstraction is the OOP principle of showing only the essential features of an object while hiding the complex implementation details. It focuses on what an object does rather than how it does it (e.g., using a Stack through push()/pop() without knowing the internal storage). In C++ it is achieved using abstract classes, pure virtual functions, and well-defined public interfaces.
Difference from Encapsulation:
| Abstraction | Encapsulation |
|---|---|
| Hides complexity / implementation details | Hides data by wrapping data and methods together |
| Focuses on the design / interface level (what to expose) | Focuses on the implementation level (how to protect data) |
| Achieved via abstract classes and interfaces | Achieved via access specifiers (private, protected, public) |
| Solves problem at design level | Solves problem at implementation level |
In short, abstraction hides complexity, while encapsulation hides data; encapsulation is often the mechanism that helps achieve abstraction.
Why can't constructors be virtual?
Constructors cannot be virtual because of how virtual mechanism and object construction work:
-
vtable not yet available: Virtual dispatch relies on the vtable pointer (vptr), which is set up by the constructor while the object is being built. Until the constructor finishes, the vptr does not exist, so a virtual call cannot be resolved at construction time.
-
Type must be known explicitly: To create an object, the compiler must know its exact type at compile time (
Derived d;ornew Derived). Virtual functions are used precisely when the type is not known until run time — the opposite of what construction requires. -
No base pointer to a not-yet-created object: Virtual functions are invoked through a base-class pointer/reference to an existing object. During construction the object does not yet exist, so there is nothing to dispatch on.
Note: A destructor can and often should be virtual (to ensure proper cleanup of derived objects through a base pointer), but a constructor cannot. The "virtual constructor" idiom is instead implemented using a virtual clone() or factory method.
What is multiple inheritance? Give an example.
Multiple inheritance is a feature of C++ in which a single derived class inherits from two or more base classes simultaneously, combining the members of all base classes into one class. Syntax:
class Derived : public Base1, public Base2 { ... };
Example:
#include <iostream>
using namespace std;
class Person {
public:
void info() { cout << "I am a person" << endl; }
};
class Employee {
public:
void work() { cout << "I work in a company" << endl; }
};
// Manager inherits from both Person and Employee
class Manager : public Person, public Employee {
public:
void manage() { cout << "I manage a team" << endl; }
};
int main() {
Manager m;
m.info(); // from Person
m.work(); // from Employee
m.manage(); // own method
return 0;
}
Note: Multiple inheritance can cause the diamond problem (ambiguity when two base classes share a common ancestor), which is resolved using virtual base classes.
Explain the throw keyword in C++.
The throw keyword in C++ is used to raise (signal) an exception when an error or abnormal condition is detected. When throw is executed, the normal flow of the program stops and control is transferred to the nearest matching catch block (stack unwinding occurs).
Syntax:
throw exception_object; // e.g. throw 0; throw "error"; throw MyException();
The value thrown can be of any type (int, char*, or an exception class object), and its type is used to select the matching catch handler.
Example:
#include <iostream>
using namespace std;
int divide(int a, int b) {
if (b == 0)
throw "Division by zero error"; // raise exception
return a / b;
}
int main() {
try {
cout << divide(10, 0);
}
catch (const char* msg) { // matching handler
cout << "Exception: " << msg << endl;
}
return 0;
}
Output: Exception: Division by zero error
A throw with no operand (throw;) inside a catch block re-throws the current exception to an outer handler.
Differentiate between text files and binary files.
Difference between Text Files and Binary Files:
| Text File | Binary File |
|---|---|
| Stores data as a sequence of human-readable characters (ASCII) | Stores data in binary form (raw bytes), exactly as in memory |
Numbers are stored as their character representation (e.g., 1234 as 4 chars) | Numbers stored in their internal byte form (e.g., 1234 as 4 bytes of an int) |
Newline \n may be translated to \r\n (on Windows) | No character translation; data stored as-is |
| Slower for numeric data; needs formatting/parsing | Faster; no conversion overhead |
| Larger size for numeric data | Generally more compact for numeric data |
| Opened with default mode | Opened with ios::binary mode |
Read/write using <<, >>, getline() | Read/write using read() and write() |
Example (binary):
ofstream f("data.bin", ios::binary);
f.write((char*)&obj, sizeof(obj));
Text files are portable and editable in any editor, whereas binary files are compact and efficient but not human-readable.
What operators cannot be overloaded in C++?
Most C++ operators can be overloaded, but a few cannot be overloaded:
.— member access (dot) operator.*— pointer-to-member access operator::— scope resolution operator?:— ternary (conditional) operatorsizeof— size-of operatortypeid— type identification operatorstatic_cast,dynamic_cast,const_cast,reinterpret_cast— the cast operators
Reason: These operators either work on the names/types of entities rather than values (e.g., ., ::, sizeof), or they have fixed semantics essential to the language that cannot safely be redefined.
Note: Operators such as =, (), [], and -> can be overloaded but only as non-static member functions (not as friend/global functions).
What is a generic class?
A generic class (called a class template in C++) is a class defined to work with any data type, where the type is supplied as a parameter when an object is created. It allows writing a single class definition that operates on different data types, promoting code reusability and type safety without rewriting the class for each type.
It is declared using the template keyword with a type parameter:
#include <iostream>
using namespace std;
template <class T> // T is a generic type
class Box {
T value;
public:
Box(T v) : value(v) {}
T get() { return value; }
};
int main() {
Box<int> b1(10); // T = int
Box<double> b2(3.14); // T = double
Box<string> b3("Hi"); // T = string
cout << b1.get() << " " << b2.get() << " " << b3.get();
return 0;
}
The same Box class works for int, double, and string. The standard library containers like vector<T>, stack<T>, and list<T> are real-world examples of generic classes.
Explain the seekg() and seekp() functions.
seekg() and seekp() are file-stream member functions used in random-access file handling to move the file position pointers.
seekg()(seek get): moves the input/get pointer in an input stream (ifstream), controlling the position from where the next read occurs.seekp()(seek put): moves the output/put pointer in an output stream (ofstream), controlling the position where the next write occurs.
Syntax:
file.seekg(offset, refpos);
file.seekp(offset, refpos);
where refpos is one of:
ios::beg— from the beginning of the fileios::cur— from the current positionios::end— from the end of the file
Example:
fstream f("data.txt", ios::in | ios::out);
f.seekg(0, ios::end); // move get pointer to end
int size = f.tellg(); // get file size
f.seekp(10, ios::beg); // move put pointer to 11th byte
f.seekg(5, ios::beg); // next read starts at 6th byte
The companion functions tellg() and tellp() return the current get and put positions respectively.
What is a member initialization list in a constructor?
A member initialization list is a syntax in a constructor used to initialize data members directly (before the constructor body executes), written after the constructor's parameter list and a colon :.
Syntax:
ClassName(params) : member1(val1), member2(val2) {
// constructor body
}
Example:
class Point {
int x, y;
const int id;
public:
Point(int a, int b, int i) : x(a), y(b), id(i) { }
};
Why it is needed / advantages:
- It is the only way to initialize
constmembers and reference members, since they must be initialized at the point of creation (cannot be assigned in the body). - Required to call a base-class constructor or a member-object constructor that has parameters.
- More efficient: members are initialized directly rather than being default-constructed and then assigned inside the body.
Members are initialized in the order they are declared in the class, not the order in the list.
Frequently asked questions
- Where can I find the BSc CSIT (TU) Object-Oriented Programming (BSc CSIT, CSC161) question paper 2079?
- The full BSc CSIT (TU) Object-Oriented Programming (BSc CSIT, CSC161) 2079 (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 (BSc CSIT, CSC161) 2079 paper come with solutions?
- Yes. Every question on this Object-Oriented Programming (BSc CSIT, CSC161) past paper includes a step-by-step solution, plus instant AI feedback when you attempt it on Kekkei.
- How many marks is the BSc CSIT (TU) Object-Oriented Programming (BSc CSIT, CSC161) 2079 paper?
- The BSc CSIT (TU) Object-Oriented Programming (BSc CSIT, CSC161) 2079 paper carries 60 full marks and is meant to be completed in 180 minutes, across 12 questions.
- Is practising this Object-Oriented Programming (BSc CSIT, CSC161) past paper free?
- Yes — reading and attempting this Object-Oriented Programming (BSc CSIT, CSC161) past paper on Kekkei is completely free.