Practice Questions for End Term Exams

Q. Define OOP. What are its major features?

Object-Oriented Programming (OOP) in C++ is a programming paradigm that organizes software around objects rather than functions. An object combines data and functions that operate on that data, creating modular, reusable, and secure programs. OOP helps manage large applications by breaking them into small interacting components.
The major features of OOP include:

  • Encapsulation – binding data and functions together

  • Abstraction – showing only essential details

  • Inheritance – creating new classes from existing ones

  • Polymorphism – same interface, different actions

These principles help reduce complexity and increase code reusability.
Example:

class Student {

private:

    int roll;

public:

    void show() { cout << roll; }

};


Q What is a class? How is it different from a structure?

A class in C++ is a user-defined data type that groups related data and functions. It serves as a blueprint for creating objects. A class supports OOP concepts such as encapsulation, abstraction, inheritance, and polymorphism.
Classes and structures differ mainly in terms of access specifiers.

  • In a class, members are private by default.

  • In a structure, members are public by default.

Classes also support advanced OOP concepts, whereas structures are mostly used for simple data grouping.
Example:

class Car {

private:

    int speed;

public:

    void setSpeed(int s){ speed = s; }

};

Structures cannot hide data by default, while classes promote data security through encapsulation.


Q. Define constructor. List its types.

A constructor in C++ is a special member function of a class that automatically executes when an object is created. Its purpose is to initialize data members. Constructors have the same name as the class and do not have a return type.
The main types of constructors are:

  1. Default Constructor – no parameters

  2. Parameterized Constructor – accepts parameters

  3. Copy Constructor – initializes object from another object

  4. Dynamic Constructor – uses dynamic memory (new)

  5. Constructor with default arguments

Example:

class Demo {

public:

    Demo() { }  

    Demo(int x) { }

    Demo(Demo &d) { }

};

Constructors ensure proper initialization and resource allocation for objects.


Q. What is function overloading? Give example.

Function overloading in C++ allows multiple functions to share the same name but differ in parameters (number or type). It improves readability and supports compile-time polymorphism. The compiler determines which function to call based on arguments passed. Overloading helps handle similar tasks with variations.
Example:

class Math {

public:

    int add(int a, int b) { return a+b; }

    double add(double a, double b) { return a+b; }

};

Both functions are named add(), but accept different parameter types. When add(5,3) is called, the integer version runs; when add(5.3,2.1) is used, the double version executes. Function overloading avoids creating unnecessary function names and makes programs easier to maintain.


Q. Explain this pointer with example.

In C++, this is a keyword that stores the address of the current object. It is automatically passed to non-static member functions. The this pointer helps distinguish between data members and parameters with the same name. It is also used for returning the current object in method chaining.
Example:

class Demo {

    int x;

public:

    void set(int x) {

        this->x = x;   // disambiguation

    }

};

Here, both the parameter and the data member have the name x, so this->x refers to the object's data member.
this is also useful in returning objects:

return *this;

It helps ensure correct object reference, especially in complex class designs.


Q. What are static data members?

Static data members in C++ are class variables shared by all objects of the class. Only one copy exists in memory, regardless of how many objects are created. They are declared using the keyword static inside the class but defined outside the class. Static members are useful for values common to all objects, such as counters or configuration values.
Example:

class Student {

public:

    static int count;

    Student() { count++; }

};

int Student::count = 0;

Each time an object is created, count increases. Static members support memory efficiency and represent common class-level properties, not object-specific ones.

Q. What is an Inline function? When should it be used?

An inline function is a function in C++ where the compiler replaces the function call with the actual function code during compilation. This reduces function call overhead, especially for small functions. Inline functions are declared using the inline keyword, though the compiler may choose to ignore the suggestion. They are beneficial for frequently called short functions such as getters, setters, or simple arithmetic operations. Inline expansion improves execution speed but increases code size, so it should not be used for large or complex functions. Functions with loops, static variables, or recursion are not ideal candidates for inlining. Overall, inline functions help optimize performance when used appropriately on small, repetitive tasks.

Q. Write the syntax of Multiple Inheritance in C++.

Multiple inheritance in C++ is a feature that allows a derived class to inherit characteristics from more than one base class. This enables designing complex systems by combining functionality from multiple sources. The general syntax includes specifying several base classes separated by commas along with their respective access specifiers, such as public, protected, or private. Multiple inheritance is powerful but can lead to ambiguity issues like the Diamond Problem, which requires virtual base classes to resolve conflicts.
Syntax:

class Derived : public Base1, public Base2 {

    // class body

};

Here, Derived inherits members from both Base1 and Base2. Careful design ensures clarity and avoids ambiguity in method resolution.

Q. What is the significance of the virtual keyword?

The virtual keyword in C++ enables runtime polymorphism by allowing derived classes to override base class functions. When a function is declared virtual, the compiler uses late binding to determine which version of the function to call based on the actual object type rather than the reference or pointer type. This is essential in inheritance when different derived classes have their own implementation of a function, such as draw() in shape classes. Without virtual, early binding would cause base class functions to execute even when using derived objects. Virtual also supports features like virtual destructors, ensuring proper cleanup of dynamically allocated objects. Overall, virtual is crucial for dynamic behavior in object-oriented programming.

Q. Define Abstract Class with an example.

An abstract class in C++ is a class that cannot be instantiated and is intended to be a base class for other classes. It contains at least one pure virtual function, which is declared using the =0 syntax. Abstract classes serve as blueprints, enforcing derived classes to implement specific behaviors. They help achieve runtime polymorphism by providing a common interface while allowing derived classes to define their own implementations. For example, a Shape class can define a pure virtual draw() function, requiring each derived shape to implement it.
Example:

class Shape {

public:

    virtual void draw() = 0;

};

This design ensures consistency while promoting flexibility in derived classes.

Q. What is the purpose of Templates in C++?

Templates in C++ enable generic programming by allowing functions and classes to operate with different data types without rewriting code. A template acts as a blueprint that generates specific functions or classes when used with particular data types. This promotes reusability, type safety, and maintainability. Templates are especially useful in implementing data structures like stacks, queues, linked lists, and algorithms that work with multiple data types. The Standard Template Library (STL) heavily relies on templates for containers, iterators, and algorithms.
Templates improve efficiency by eliminating redundant code and enabling compile-time type resolution. They support both function templates and class templates, making C++ a powerful language for building flexible and type-independent components.

Q. Explain the concept of Objects and Classes with suitable examples.

A class in C++ is a user-defined data type that acts as a blueprint for creating objects. It contains data members and member functions that define the behavior and properties of the objects created from it. A class does not occupy memory until an object is created. An object is an instance of a class and represents real-world entities such as a student, car, or employee. For example, if we define a class Car with attributes like model and speed, objects such as car1 and car2 can be created with different values. Classes allow code reusability and encapsulation, while objects help structure programs into meaningful components that interact with one another.

Q. What is a Copy Constructor? Explain with an example.

A copy constructor in C++ is a special constructor used to create a new object as a copy of an existing object. It takes a reference to an object of the same class as its parameter. The primary purpose is to ensure safe copying of objects, especially when they contain pointers or dynamically allocated memory. If not defined explicitly, C++ creates a default copy constructor that performs shallow copy. However, programmers often create custom copy constructors to perform deep copy and prevent issues like double deletion.
Example:

class Sample {

    int x;

public:

    Sample(int a){ x=a; }

    Sample(const Sample &s){ x = s.x; }

};

This ensures the new object receives the same value as the original.

Q. Explain Dynamic Memory Allocation with example code.

Dynamic memory allocation allows allocating memory at runtime using the new keyword. It is useful when the size of data structures is not known beforehand. Memory created with new remains allocated until explicitly released using delete, preventing memory leaks. It is mainly used in pointer-based programming, dynamic arrays, and data structures like linked lists.
Example:

int *p = new int;      // allocate memory

*p = 10;

delete p;             // free memory

Dynamic memory provides flexibility but requires careful management.

Q. Write program to demonstrate multilevel inheritance

Multilevel inheritance forms a chain of classes where one class inherits from another, and a further class inherits from it. This structure models hierarchical relationships.

#include<iostream>

using namespace std;

class A {

public:

    void showA(){ cout<<"Class A\n"; }

};

class B : public A {

public:

    void showB(){ cout<<"Class B\n"; }

};

class C : public B {

public:

    void showC(){ cout<<"Class C\n"; }

};

int main(){

    C obj;

    obj.showA();

    obj.showB();

    obj.showC();

}

Q. What is Polymorphism? Explain compile-time and run-time polymorphism.

Polymorphism means “many forms” and allows functions or objects to behave differently based on context. Compile-time polymorphism is achieved through function overloading and operator overloading. It is resolved by the compiler using early binding. Run-time polymorphism is achieved through function overriding using virtual functions. The correct function is selected at runtime through late binding, depending on the object type. Polymorphism enables flexible code, improves reusability, and supports object substitution principles in OOP. It also allows building extensible systems where child classes can replace or extend parent class behavior without modifying existing code.


Q. What is operator overloading?

Operator overloading in C++ allows predefined operators such as +, -, ==, and << to operate on user-defined objects. It enhances readability by enabling natural syntax for object operations. Operator overloading is implemented using the keyword operator followed by the symbol. It supports compile-time polymorphism.
Example:

class Complex {

    int r, i;

public:

    Complex(int a, int b) : r(a), i(b) {}

    Complex operator +(Complex c) {

        return Complex(r + c.r, i + c.i);

    }

};

Now, two complex objects can be added using:

c3 = c1 + c2;

Operator overloading improves intuitive usage of custom classes.


Q. Define inheritance. Mention any two types.

Inheritance in C++ enables a class (derived class) to acquire properties and behaviors of another class (base class). It promotes code reusability, extensibility, and hierarchical relationships.
Two common types of inheritance include:

  1. Single Inheritance – one base class and one derived class

  2. Multilevel Inheritance – a derived class becomes a base for another class

Other types include multiple, hierarchical, and hybrid inheritance.
Example:

class A { };

class B : public A { };  // single inheritance

class C : public B { };  // multilevel inheritance

Inheritance reduces redundancy and allows modification of base functionality in derived classes.


Q. What is a pure virtual function?

A pure virtual function in C++ is a function declared in a base class with no definition. It forces derived classes to provide their own implementation. It is declared using = 0. Classes containing pure virtual functions become abstract classes, meaning no object can be created from them.
Example:

class Shape {

public:

    virtual void draw() = 0;  // pure virtual

};

class Circle : public Shape {

public:

    void draw() { cout << "Circle"; }

};

This ensures that every derived class must implement the draw() function. Pure virtual functions support runtime polymorphism and abstraction.


Q. What is exception handling? Write its syntax.

Exception handling in C++ is a mechanism to detect and manage runtime errors without crashing the program. It ensures program stability by separating normal execution from error-handling logic. C++ uses try, throw, and catch keywords for exception handling.
Syntax:

try {

    // code that may generate error

    throw exception;

}

catch(type e) {

    // handling code

}

Example:

try {

    int a = 10, b = 0;

    if(b == 0) throw "Division by zero!";

}

catch(const char* msg) {

    cout << msg;

}

Exception handling improves program safety and reliability.


Q. Define Encapsulation with example.

Encapsulation in C++ is a fundamental object-oriented concept in which data and functions that operate on that data are bundled together into a single unit called a class. It protects data by restricting direct access and allowing interaction only through public methods. By hiding sensitive information using private or protected access specifiers, encapsulation ensures controlled data manipulation and prevents accidental misuse. This improves security, modularity, and maintainability of programs. 

A real-life example is a bank account system: the account balance is private and cannot be changed directly; instead, functions like deposit(), withdraw(), and checkBalance() manage it. 

The user interacts only through these methods, ensuring safe and controlled operations on the data.


Q. What is a Parameterized Constructor?

A parameterized constructor in C++ is a special constructor that accepts one or more parameters to initialize object data members when the object is created. Instead of assigning default values or manually setting values after object creation, parameterized constructors allow initializing variables directly during instantiation. This enhances code flexibility, reduces errors, and ensures objects always start with meaningful values. Parameterized constructors are especially useful when different objects require different initial states. For example, in a class representing a student, roll number and marks can be passed as arguments.

class A {

    int x;

public:

    A(int a) { x = a; }

};

Here, A obj(10); initializes x with 10.


Q. What is early binding and late binding.

Early binding, also known as static binding or compile-time binding, occurs when the function call is resolved at compile time. It is used in function overloading and operator overloading. Since the binding happens early, execution is faster but less flexible. Late binding, or dynamic binding, resolves the function call at runtime and is used with virtual functions in inheritance. It supports runtime polymorphism and allows the program to choose the correct function based on the actual object type rather than reference type. Late binding offers greater flexibility but may have a slight performance overhead. In summary, early binding is faster and used in compile-time polymorphism, while late binding supports runtime polymorphism and dynamic behavior.

Q. What are Friend Functions?

A friend function in C++ is a special function that is not a member of a class but is granted access to the class’s private and protected members. It is declared using the keyword friend within the class. Friend functions are useful when two or more classes need to share confidential data or when an external function must access internal data while still maintaining encapsulation for general use.

Yes, a friend function can access private members directly because the class explicitly grants permission. This does not violate encapsulation since access is controlled and intentional. Friend functions are commonly used in operator overloading, especially when overloading binary operators that require access to private data of both operands.


Q. Explain Function Overloading and Operator Overloading?

Function overloading allows multiple functions to share the same name with different parameter lists. The compiler determines which function to call based on the arguments provided, supporting compile-time polymorphism. Operator overloading, on the other hand, extends the functionality of operators like +, -, *, or == so they can operate on user-defined types such as objects. This enhances code readability by enabling objects to behave like built-in types.

While function overloading is purely syntactic and focuses on naming convenience, operator overloading modifies how operators behave. Both support polymorphism, but operator overloading must follow specific rules and cannot change operator precedence or create new operators. It improves intuitive interaction with objects in programs.


Q. Write a Program for Student class having suitable data members?

To represent student information using OOP, we create a class Student that contains data members like roll number, name, and marks. Member functions allow reading and displaying the details. Creating objects of the class enables handling multiple student records easily. This promotes encapsulation because all operations are performed through class methods without exposing internal variables directly. Below is the required program: 

#include<iostream>

using namespace std;

class Student {

public:

    int rollno;

    string name;

    float marks;

    void getData() {

        cin >> rollno >> name >> marks;

    }

    void show() {

        cout << rollno << " " << name << " " << marks;

    }

};

int main() {

    Student s;

    s.getData();

    s.show();

}


Q. Explain Function Overloading.

Function overloading is a compile-time polymorphism technique where multiple functions have the same name but differ in the number or type of parameters. It allows programmers to create functions that perform similar tasks but accept different inputs. For example, adding two integers and adding two floats can be done using overloaded functions with the same name add(). 

The compiler selects the appropriate function based on the argument list.

Example:

int add(int a,int b){ return a+b; }

float add(float a,float b){ return a+b; }

Overloading improves readability and eliminates the need for different function names for similar tasks.


Q. Write a Program to overload + operator for complex numbers 

Operator overloading allows redefining operators for user-defined types. In complex number operations, the + operator can be overloaded to add real and imaginary parts of two complex objects. By creating a member function operator+, we ensure correct addition and return a new object.

#include<iostream>

using namespace std;

class Complex {

    int r, i;

public:

    Complex(int a=0,int b=0){ r=a; i=b; }


    Complex operator+(Complex c){

        return Complex(r + c.r, i + c.i);

    }

    void show(){ cout << r << " + " << i << "i"; }

};


int main(){

    Complex c1(2,3), c2(4,5), c3;

    c3 = c1 + c2;

    c3.show();

}


Q, Explain various types of inheritance in C++.

C++ supports five main types of inheritance. 

  • Single inheritance allows a class to inherit from one base class. 
  • Multiple inheritance enables a derived class to inherit from more than one base class. 
  • Multilevel inheritance involves a class derived from another derived class, forming a chain. 
  • Hierarchical inheritance allows several classes to inherit from the same base class. 
  • Hybrid inheritance is a combination of these types and may involve virtual base classes to avoid ambiguity. 

Each type serves specific design needs, promoting reusability and structural clarity in programs. C++ handles these forms efficiently using access specifiers that control visibility of inherited members.


Q. Explain Virtual Functions and Pure Virtual Functions with examples

A virtual function in a base class allows derived classes to override it, enabling runtime polymorphism. When a base class pointer refers to derived objects, the overridden function executes based on the actual object.

Example:

class Base{ public: virtual void show(){} };

A pure virtual function (virtual void show() = 0;) makes a class abstract and forces derived classes to implement the function. Pure virtual functions define interfaces.


Q. Explain Static Data Members and Static Member Functions

A static data member belongs to the class rather than individual objects. Only one copy exists, shared by all objects. It is declared using the keyword static and must be defined outside the class. Static member functions can access only static members and are invoked using class name. They are useful for maintaining counters, tracking objects, or storing class-level settings. Static members provide memory efficiency and global accessibility without needing objects.


Q. Write a Program to count objects using static member

#include<iostream>

using namespace std;

class Demo {

    static int count;

public:

    Demo(){ count++; }

    static void show(){ cout<<"Objects: "<<count; }

};

int Demo::count = 0;

int main(){

    Demo a,b,c;

    Demo::show();

}


Q. Explain Constructors and Destructors

Constructors are special member functions used to initialize objects when they are created. They have the same name as the class and no return type. Types include default constructor, which assigns initial values; parameterized constructor, which accepts arguments; copy constructor, which creates a new object as a copy of an existing one; and constructor overloading, where multiple constructors are defined to handle different initialization scenarios. Destructors, on the other hand, are invoked automatically when an object goes out of scope. They free resources, close files, or release memory. A destructor has the name preceded by a tilde (~). Proper use of constructors and destructors ensures safe memory management and clean object lifecycle handling in C++ programs.


Q. Write a Program demonstrating constructor overloading

#include<iostream>

using namespace std;

class Demo {

    int x,y;

public:

    Demo(){ x=0; y=0; }

    Demo(int a){ x=a; y=0; }

    Demo(int a,int b){ x=a; y=b; }


    void show(){ cout<<x<<" "<<y; }

};

int main(){

    Demo d1, d2(5), d3(3,4);

    d1.show();

    d2.show();

    d3.show();

}


Q. Explain Operator Overloading rules and limitations

Operator overloading lets operators like +, -, *, == work with user-defined types. Rules: you cannot change operator precedence or syntax, cannot create new operators, and overloaded operators must have at least one operand as a user-defined type. Certain operators like ::, ., ?:, and sizeof cannot be overloaded. The purpose is to make objects behave similarly to built-in types. Limitations include risk of confusing code if operators are overloaded incorrectly, and overuse may reduce readability. Operator overloading should always represent natural behavior, such as adding two complex numbers.


Q. Write a Program to overload – operator

#include<iostream>

using namespace std;


class Point{

    int x,y;

public:

    Point(int a,int b){ x=a;y=b; }

    Point operator-(){

        return Point(-x,-y);

    }

    void show(){ cout<<x<<" "<<y; }

};

int main(){

    Point p1(3,4), p2;

    p2 = -p1;

    p2.show();

}


Q. What is Virtual Base Class? Why is it needed?

A virtual base class is used in multiple inheritance to avoid duplication of base class members. It ensures only one copy of a base class is inherited, even when several paths lead to it. This is essential in the diamond problem where two intermediate classes inherit from a single base class and a derived class inherits from both. Without virtual inheritance, the derived class gets two copies of the base class, causing ambiguity.

Using virtual base classes resolves ambiguity and ensures a clear, common base.


Q. Explain Exception Handling

Exception handling manages runtime errors and prevents abnormal program termination. In C++, try block contains code that may throw an exception. The throw keyword generates the exception, passing control to the catch block that handles it. This mechanism separates error-handling logic from normal code, improves reliability, and helps recover gracefully from unexpected situations such as division by zero, memory failure, or invalid input.


Q. Write a Program with multiple catch blocks

#include<iostream>

using namespace std;


int main(){

    try{

        int x; cin>>x;

        if(x==0) throw "Zero";

        if(x<0) throw x;

        cout<<"Valid";

    }

    catch(const char *s){ cout<<"Error: "<<s; }

    catch(int n){ cout<<"Negative: "<<n; }

}


Q. Explain Class Templates and Function Templates

Class templates allow creating generic classes that work with different data types. Instead of writing multiple versions of a class, a single template handles int, float, double, etc. Function templates allow writing one function for many data types. Templates provide flexibility and type safety in C++. STL uses templates extensively for vectors, lists, stacks, and algorithms.


Q. Write code for Template to find largest of three numbers

template <class T>

T largest(T a,T b,T c){

    if(a>=b && a>=c) return a;

    else if(b>=c) return b;

    else return c;

}


Q. Explain the structure of a C++ program with an example.

A C++ program follows a well-defined structure consisting of headers, namespaces, classes or functions, and the main() function. The program usually starts with preprocessor directives, such as #include <iostream>, which include necessary libraries. The using namespace std; statement allows simpler access to standard functions. Classes and function definitions follow, forming the main logic of the application. Finally, execution starts from the main() function, which returns an integer and contains program statements. A well-structured program enhances readability and modularity.
Example:

#include <iostream>

using namespace std;


class Demo {

public:

    void show() { cout << "Hello"; }

};


int main() {

    Demo d;

    d.show();

    return 0;

}


Q. Discuss the concept of data abstraction and encapsulation.

Data abstraction in C++ means showing only essential information while hiding unnecessary internal details. It helps users interact with objects through simple interfaces. Encapsulation combines data and functions into a single unit (class) and restricts direct access using access specifiers—private, protected, and public. Together, they ensure security and modularity.
Example:

class Bank {

private:

    int balance;  // hidden data

public:

    void deposit(int amt) { balance += amt; }

    int getBalance() { return balance; }

};

Here, the variable balance is hidden from outside access, providing abstraction while the class structure binds data and functions together, providing encapsulation. These principles prevent accidental modification and protect program integrity.


Q. Explain dynamic memory allocation in C++ using new and delete.

Dynamic memory allocation allows memory to be assigned at runtime instead of compile time. In C++, the new operator allocates memory from the heap, while delete frees that memory to prevent memory leaks. This is essential when memory needs cannot be predetermined.
Example:

int *ptr = new int;  

*ptr = 20;

delete ptr;

For arrays:

int *arr = new int[5];

delete[] arr;

new returns the address of the memory allocated, which can be stored in a pointer. Proper use of delete ensures efficient memory management. Dynamic allocation is widely used for creating objects and arrays whose size depends on runtime conditions.


Q. What is a friend function? Show how to declare and use one.

A friend function in C++ is a non-member function that is allowed to access the private and protected members of a class. It is declared using the keyword friend inside the class. Friend functions are useful when external functions need controlled access to hidden data, especially in operator overloading or when two classes need to share data.
Example:

class Box {

private:

    int length;

public:

    Box(int l) : length(l) {}

    friend void show(Box b);

};


void show(Box b) {

    cout << "Length = " << b.length;

}

Here, the function show() is not a member of the class but still accesses private data. Friend functions break encapsulation only where necessary and provide flexibility.


Q. Describe different types of constructors with suitable examples.

Constructors are special member functions invoked automatically when an object is created. They initialize data members and ensure the object starts in a valid state.
Types of constructors:

  1. Default Constructor – No parameters.

  2. Parameterized Constructor – Accepts arguments for initialization.

  3. Copy Constructor – Creates a new object using an existing object.

  4. Dynamic Constructor – Allocates dynamic memory inside the constructor.

Example:

class Demo {

    int x;

public:

    Demo() { x = 0; }                 // default

    Demo(int a) { x = a; }            // parameterized

    Demo(Demo &d) { x = d.x; }        // copy

};

Constructors simplify object setup and reduce the chance of uninitialized data. They also support object cloning and dynamic resource allocation.


Q. Explain copy constructor and its necessity.

A copy constructor initializes an object using another object of the same class. It has the form:
ClassName(const ClassName &obj).
Copy constructors are automatically called during:

  • Passing objects by value

  • Returning objects

  • Creating new objects from existing ones

They prevent shallow copying, especially when a class contains pointers or dynamically allocated memory.
Example:

class Sample {

    int *p;

public:

    Sample(int x) {

        p = new int(x);

    }

    Sample(const Sample &s) {   // deep copy

        p = new int(*s.p);

    }

};

Without a copy constructor, both objects would share the same memory, causing runtime errors. Hence, copy constructors ensure safe duplication of objects.


Q. Explain operator overloading. Overload the + operator for a complex number class.

Operator overloading allows operators like +, -, and == to work with user-defined objects. It enhances readability and makes object operations intuitive. The keyword operator is used for overloading.
Example of overloading + for Complex numbers:

class Complex {

    int r, i;

public:

    Complex(int a=0, int b=0) : r(a), i(b) {}

    Complex operator +(Complex c) {

        return Complex(r + c.r, i + c.i);

    }

};

Now, Complex objects can be added using natural syntax:

Complex c1(2,3), c2(4,5);

Complex c3 = c1 + c2;

Operator overloading enables objects to behave similarly to built-in types, supporting polymorphism and improving code clarity.


Q. What is function overriding? How is it different from overloading?

Function overriding occurs when a derived class redefines a base class function with the same name, return type, and parameters. It supports runtime polymorphism and requires inheritance.
Example:

class Base {

public:

    virtual void show() { cout << "Base"; }

};

class Derived : public Base {

public:

    void show() override { cout << "Derived"; }

};

Overloading vs Overriding:

  • Overloading happens within the same class, with different parameter lists (compile-time polymorphism).

  • Overriding happens across base–derived classes with identical signatures (runtime polymorphism).

Overriding allows specialized behavior in derived classes while retaining a common interface.


Q. Explain single, multilevel, and multiple inheritance with diagrams.

Inheritance allows a class to acquire properties of another class.
1. Single Inheritance – One base class and one derived class.

A → B

2. Multilevel Inheritance – A derived class becomes the base for another derived class.

A → B → C

3. Multiple Inheritance – A derived class inherits from more than one base class.

 A

   \  

    C

   /

 B

Example:

class A { };

class B : public A { };      // single


class C : public B { };      // multilevel


class D { };

class E : public A, public D { };  // multiple

These forms allow reusability and flexibility. However, multiple inheritance may lead to ambiguity issues solved through virtual base classes.


Q. What are virtual base classes? Why are they used?

Virtual base classes prevent duplication of base class members when using multiple inheritance, especially in the diamond problem. In this scenario, two intermediate classes inherit from the same base class, and a final class inherits from both, causing multiple copies of the base class.
Using the keyword virtual ensures that only one shared instance of the base class exists.
Example:

class A { public: int x; };

class B : virtual public A { };

class C : virtual public A { };

class D : public B, public C { };

Here, class D inherits only one copy of class A.
Virtual base classes reduce ambiguity, save memory, and ensure consistent base class behavior in complex hierarchies.


Q. Write a program to demonstrate hierarchical inheritance.

Hierarchical inheritance occurs when multiple derived classes inherit from a single base class. It allows sharing common features while specializing in derived classes.
Example:

#include <iostream>

using namespace std;


class Shape {

public:

    void display() { cout << "This is a shape\n"; }

};


class Circle : public Shape {

public:

    void show() { cout << "Circle shape\n"; }

};


class Rectangle : public Shape {

public:

    void show() { cout << "Rectangle shape\n"; }

};


int main() {

    Circle c;

    Rectangle r;

    c.display(); c.show();

    r.display(); r.show();

    return 0;

}

Both Circle and Rectangle inherit common behavior from Shape, demonstrating hierarchical inheritance and code reusability.


Q. Explain the diamond problem in C++.

The diamond problem occurs in multiple inheritance when two derived classes inherit from the same base class, and a final class inherits from both. This creates two copies of the base class within the final class, causing ambiguity.
Structure:

    A  

   / \  

  B   C  

   \ /

    D

If both B and C contain a copy of A, class D inherits both copies, leading to conflicts such as:

D obj;

obj.x; // ambiguous

Solution: Use virtual inheritance to ensure only one copy of the base class is shared.

class B : virtual public A {};

class C : virtual public A {};

Virtual base classes eliminate ambiguity and ensure consistent inheritance paths.


Q. What is a virtual function? Explain run-time polymorphism with an example.

A virtual function is a member function declared with the keyword virtual in the base class and redefined in the derived class. It enables run-time polymorphism, where the function call is resolved during execution based on the object type, not the pointer type. Virtual functions use dynamic binding (late binding) via the virtual table (v-table). This allows derived classes to provide specialized behavior while maintaining a common interface.

Example:

class Base {

public:

    virtual void show() { cout << "Base\n"; }

};

class Derived : public Base {

public:

    void show() override { cout << "Derived\n"; }

};


int main() {

    Base* ptr = new Derived;

    ptr->show();  // prints Derived

}

Run-time polymorphism supports flexibility and extensibility in OOP.


Q. What is an abstract class? Give an example.

An abstract class is a class that contains at least one pure virtual function. It cannot be instantiated directly but serves as a blueprint for derived classes. Abstract classes enforce a common interface, ensuring that all derived classes implement specific functions. They promote abstraction, creating a strong foundation for polymorphism.

Example:

class Shape {

public:

    virtual void draw() = 0;  // pure virtual function

};


class Circle : public Shape {

public:

    void draw() { cout << "Drawing Circle"; }

};


int main() {

    Shape* s = new Circle();

    s->draw();

}

Here, Shape is abstract and cannot create objects, but it guarantees that every shape class implements draw(). This improves consistency and design structure.


Q. What is exception handling? Explain the try–catch mechanism.

Exception handling in C++ provides a structured way to detect and manage runtime errors. It prevents program crashes and ensures smooth error recovery. The mechanism uses try, throw, and catch blocks. Code that may cause an error is placed in a try block. When an error occurs, a value or object is thrown, and the corresponding catch block handles it. This separates error-handling logic from normal logic, improving program reliability.

Example:

try {

    int a = 10, b = 0;

    if(b == 0)

        throw "Division by zero!";

}

catch(const char* msg) {

    cout << msg;

}

The program continues running even after encountering the error, ensuring stability and safety.


Q. Write a program that handles division-by-zero exception.

Below is a simple C++ program that demonstrates handling a division-by-zero error using exception handling. It prevents the program from terminating abnormally and prints a custom error message.

Example Program:

#include <iostream>

using namespace std;


int main() {

    int a, b;

    cout << "Enter two numbers: ";

    cin >> a >> b;


    try {

        if(b == 0)

            throw "Error: Division by zero!";

        cout << "Result = " << a / b;

    }

    catch(const char* msg) {

        cout << msg;

    }


    return 0;

}

The program throws an exception when b is zero and catches it gracefully, ensuring safe execution. This demonstrates practical exception handling in C++.


Q. Explain the concept of file handling in C++. What are different file modes?

File handling in C++ allows programs to store and retrieve data permanently using files. The <fstream> library provides three main classes:

  • ifstream – for reading

  • ofstream – for writing

  • fstream – for both reading and writing

File handling involves opening a file, performing read/write operations, and closing it. Different file modes define how the file is accessed:

  • ios::in → open for reading

  • ios::out → open for writing

  • ios::app → append to end

  • ios::trunc → delete existing content

  • ios::binary → binary mode

  • ios::ate → open and go to end

Example:

ofstream fout("data.txt", ios::out);

fout << "Hello";

fout.close();

File handling supports persistence and safe data management.


Q. Write a program to read and write objects to a file.

Below program demonstrates writing and reading an object using binary file handling in C++. It uses ofstream and ifstream with write() and read() functions.

Example Program:

#include <iostream>

#include <fstream>

using namespace std;


class Student {

    int roll;

    char name[20];

public:

    void getData() {

        cout << "Enter roll and name: ";

        cin >> roll >> name;

    }

    void showData() {

        cout << roll << " " << name << endl;

    }

};


int main() {

    Student s1, s2;

    s1.getData();


    // Write object

    ofstream fout("stud.dat", ios::binary);

    fout.write((char*)&s1, sizeof(s1));

    fout.close();


    // Read object

    ifstream fin("stud.dat", ios::binary);

    fin.read((char*)&s2, sizeof(s2));

    s2.showData();


    return 0;

}

This demonstrates persistent object storage using files.


Q. Describe templates in C++ with an example.

Templates enable generic programming, allowing functions and classes to operate with any data type. They reduce code repetition by using a placeholder type, typically T, replaced during compilation. Templates help build flexible and reusable components, such as generic stacks, arrays, or sorting functions.

Example — Function Template:

template <class T>

T add(T a, T b) {

    return a + b;

}


int main() {

    cout << add(5, 10);       // int

    cout << add(5.5, 2.3);    // double

}

Templates work with any type that supports the required operations. They enhance extensibility and allow algorithms to be written once and applied to many data types without rewriting code.


Q. What are class templates? Write an example.

Class templates allow entire classes to operate with generic data types. They are useful for implementing data structures such as stacks, queues, linked lists, and vectors. A type parameter is supplied when an object of the class is created.

Example — Class Template:

template <class T>

class Box {

    T value;

public:

    Box(T v) { value = v; }

    void show() { cout << value; }

};


int main() {

    Box<int> b1(10);

    Box<string> b2("Hello");

    b1.show();

    b2.show();

}

Here, the same class works for both int and string types. Class templates simplify coding and support reusable, type-independent class designs.


No comments:

Post a Comment