Explain the term Data hiding
Data hiding is a concept in computer programming and software engineering that involves restricting
access to certain details of an object or class to ensure controlled interaction and safeguard its integrity.
It is a fundamental principle of object-oriented programming (OOP) and closely related to the idea of
encapsulation.
Benefits:
    1. Security: Protects sensitive data from unauthorized access.
    2. Modularity: Changes in the internal implementation of a class don't affect the external
       interface.
    3. Error Prevention: Minimizes the risk of introducing errors by enforcing controlled data
       manipulation.
    4. Maintenance: Simplifies debugging and future enhancements by isolating internal data.
Explain access specifiers.
Access specifiers in object-oriented programming define the level of access control for members
(variables and methods) of a class. They determine whether other classes or objects can access
these members.Access specifiers are a crucial part of encapsulation, which helps secure the
internal workings of a class while providing controlled interaction through specific interfaces.
Types of Access Specifiers
1. Public
       Members declared as public are accessible from anywhere in the program.
       There are no restrictions on the visibility of public members.
       Suitable for defining the interface of a class, such as methods or constants meant to be used
        widely.
2. Private
       Members declared as private are accessible only within the class in which they are defined.
       These members cannot be accessed directly by objects of the class or outside functions.
       Used to hide sensitive data and implementation details from the outside world
3. Protected
       Members declared as protected are accessible within the class in which they are defined and
        in any derived (child) classes.
       Not accessible by objects or other unrelated classes.
       Commonly used when implementing inheritance.
How the ambiguity in multiple inheritance can be resolved
In multiple inheritance, ambiguity can arise when two or more base classes have a member
(variable or function) with the same name, and a derived class inherits from these base classes.
The compiler is unsure which version of the member to access, leading to ambiguity.
Using Scope Resolution Operator (::) to Resolve Ambiguity in Multiple Inheritance
      Explicitly specify the class from which the member should be accessed using the scope
       resolution operator (::).
Example:
#include <iostream>
using namespace std;
class A {
public:
    void display() {
        cout << "Display from Class A" << endl;
    }   };
class B {
public:
    void display() {
        cout << "Display from Class B" << endl;
    }    };
class C : public A, public B {
public:
    void resolveAmbiguity() {
        A::display(); // Call display() from Class A
        B::display(); // Call display() from Class B
    }                        };
int main() {
    C obj;
    obj.resolveAmbiguity();
    return 0;
}
Explain virtual base class
A virtual base class is a mechanism in C++ that prevents multiple copies of a base class being
inherited when a derived class is created from multiple inheritance paths. This concept is
particularly useful in resolving the diamond problem.
The Diamond Problem
In multiple inheritance, a derived class may inherit the same base class through multiple
intermediate classes. This can lead to ambiguity and duplication of the base class members.
Syntax for Virtual Base Class:
class Base {};
class Derived1 : virtual public Base {};
class Derived2 : virtual public Base {};
class FinalDerived : public Derived1, public Derived2 {};
Explain aggregation
Aggregation is a concept in object-oriented programming that describes a "has-a" relationship
between two classes. It is a type of association where one class contains a reference to another
class as a part of its structure. Aggregation represents a weak ownership relationship, meaning
the lifetime of the contained object is independent of the container class.
Features of oops
Object-Oriented Programming (OOP) is a programming paradigm based on the concept of
objects, which encapsulate data and behavior. OOP has several features that make it powerful,
modular, and scalable for modern software development.
Key Features of OOP:
1. Encapsulation
        Encapsulation is the bundling of data (attributes) and methods (functions) that operate on the
         data into a single unit called a class.
2. Inheritance
        Inheritance allows a class (child or derived class) to inherit properties and behavior from
         another class (parent or base class).
3. Polymorphism
        Polymorphism means "many forms" and allows a single interface to represent different
         underlying data types or methods.
        It can be achieved through:
              o Compile-time polymorphism (Method Overloading): Same function name, different
                  signatures.
              o Run-time polymorphism (Method Overriding): A derived class modifies or extends the
                  functionality of a base class method.
4. Abstraction
       Abstraction focuses on hiding the implementation details and showing only the essential
        features of an object.
5. Modularity
       OOP promotes breaking down complex systems into smaller, manageable components (classes).
       This makes code easier to maintain, debug, and reuse.
6. Dynamic Binding
       In OOP, method calls are resolved at runtime if polymorphism is used. This is known as dynamic
        (or late) binding.
How to define member function outside the class? Give Example.
        In C++, you can define a member function outside the class by using the scope
        resolution operator (::). The function declaration is provided inside the class, and its
        definition is written outside using the syntax:
        return_type ClassName::FunctionName(parameters) {
            // Function body
        }
        EXAMPLE 
#include <iostream>
using namespace std;
class Rectangle {
private:
    int length, width;
public:
    // Declaration of member functions
    void setDimensions(int l, int w);
    int calculateArea();
    void display();
};
void Rectangle::setDimensions(int l, int w) {
    length = l;
    width = w;     }
int Rectangle::calculateArea() {
    return length * width;     }
void Rectangle::display() {
    cout << "Length: " << length << ", Width: " << width << endl;   }
int main() {
    Rectangle rect;
    rect.setDimensions(10, 5);
    rect.display();
    cout << "Area: " << rect.calculateArea() << endl;
    return 0; }
Explain concept of reusability with example
Reusability is a fundamental principle of object-oriented programming (OOP) that allows
developers to use existing code in new applications or contexts without rewriting it. It helps
reduce development time, improve productivity, and maintain consistency across a project.
Reusability can be achieved through various OOP mechanisms like inheritance, composition,
polymorphism, and modularity. Among these, inheritance is the most common way to achieve
reusability.
Give definition of Genric classes
A generic class in C++ is a class that can work with any data type. It allows the creation of a
single class template that can be instantiated with different data types without having to rewrite
the class for each data type.
In C++, generic classes are implemented using class templates, which enable the definition of a
class with type parameters. These type parameters are placeholders for the data types, and they
are replaced with actual types when the class is instantiated.