C++ Revision Day-5

ยท

7 min read

1) What is an abstract class in C++?

An abstract class in C++ is such that cannot be used directly and is used to form a base class for others to inherit from.

If you create an object for an abstract class the compiler will throw an error at you.

In C++, an abstract class is a class that cannot be instantiated and is typically used as a base class for other classes. An abstract class is defined by including at least one pure virtual function. A pure virtual function is a function that has no implementation in the abstract class and must be overridden in any derived class.

#include <iostream>
using namespace std;

// Abstract class
class Shape {
public:
    // Pure virtual function
    virtual void draw() = 0;
    virtual double area() = 0;

    void info() {
        cout << "This is a shape." << endl;
    }
};

// Derived class
class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : radius(r) {}

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

    double area() override {
        return 3.14159 * radius * radius;
    }
};

// Another derived class
class Rectangle : public Shape {
private:
    double width, height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}

    void draw() override {
        cout << "Drawing a Rectangle" << endl;
    }

    double area() override {
        return width * height;
    }
};

int main() {
    Shape* shape1 = new Circle(5.0);
    Shape* shape2 = new Rectangle(4.0, 6.0);

    shape1->draw();
    cout << "Area of Circle: " << shape1->area() << endl;

    shape2->draw();
    cout << "Area of Rectangle: " << shape2->area() << endl;

    delete shape1;
    delete shape2;

    return 0;
}

2) What is Containership in C++?

Containership is a relationship in which a class's object is nested inside another class. The class which stores the object is called container and the class whose object is stored in class contained class.

Containership, also known as composition or aggregation, is a design principle in C++ where a class contains objects of other classes as member variables. This helps in building complex types from simpler ones. Containership models a "has-a" relationship, meaning that one class contains or has objects of another class.

#include <iostream>
#include <string>
using namespace std;

// Class representing an Engine
class Engine {
private:
    int horsepower;

public:
    Engine(int hp) : horsepower(hp) {}

    int getHorsepower() const {
        return horsepower;
    }
};

// Class representing a Car that contains an Engine
class Car {
private:
    string brand;
    Engine engine;  // Composition: Car contains an Engine object

public:
    Car(const string& br, int hp) : brand(br), engine(hp) {}

    void display() const {
        cout << "Car brand: " << brand << endl;
        cout << "Engine horsepower: " << engine.getHorsepower() << endl;
    }
};

int main() {
    Car myCar("Toyota", 200);
    myCar.display();

    return 0;
}

3) What is data hiding in C++?

An object-oriented technique of hiding data members is called data hiding. In other words, giving restricted access to the data members so as to maintain object integrity.

4) What is Method Overloading?

Method overloading occurs when multiple methods in the same class have the same name but different parameter lists (different types or numbers of parameters). It is a compile-time polymorphism.

Key Points:

  1. Same Class: Overloading happens within the same class.

  2. Different Parameters: The overloaded methods must have different parameter lists (either in the number of parameters or their types).

  3. Compile-time: The method to be called is determined at compile time-based on the method signature.

#include <iostream>
using namespace std;

class Print {
public:
    void show(int i) {
        cout << "Integer: " << i << endl;
    }

    void show(double d) {
        cout << "Double: " << d << endl;
    }

    void show(string s) {
        cout << "String: " << s << endl;
    }
};

int main() {
    Print p;
    p.show(10);       // Calls show(int)
    p.show(5.5);      // Calls show(double)
    p.show("Hello");  // Calls show(string)

    return 0;
}

5) What is Function Overriding?

Function overriding occurs when a derived class has a definition for one of the member functions of the base class. This base function should be declared with the virtual keyword in the base class. It is a runtime polymorphism.

Key Points:

  1. Different Classes: Overriding happens in the context of inheritance, i.e., between base and derived classes.

  2. Same Signature: The overridden method must have the same signature as the method in the base class.

  3. Runtime: The method to be called is determined at runtime based on the object type (dynamic binding).

6) Can we have Method Overloading and Function Overriding both at the same time ?

Yes.

#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() {  // Virtual function for overriding
        cout << "Base class show()" << endl;
    }
};

class Derived : public Base {
public:
    void show() override {  // Overriding the base class function
        cout << "Derived class show()" << endl;
    }

    void show(int i) {  // Overloading the function in the derived class
        cout << "Derived class show(int): " << i << endl;
    }
};

int main() {
    Base* b = new Derived();
    b->show();  // Calls Derived's show() - overriding

    Derived d;
    d.show();  // Calls Derived's show() - overriding
    d.show(10);  // Calls Derived's show(int) - overloading

    delete b;
    return 0;
}

7) What is a Copy Constructor in C++?

A copy constructor is a constructor in C++ which creates an object by initializing it with an object of the same class, which has been made previously.
The syntax for the copy constructor is as follows:

A copy constructor in C++ is a special type of constructor that creates a new object as a copy of an existing object of the same class. It initializes a new object using another object of the same class, typically passed as a parameter.

class MyClass {
public:
    int data;

    // Copy constructor declaration
    MyClass(const MyClass& other) {
        data = other.data;  // Copy data from 'other' to 'this' object
    }
};

int main() {
    MyClass obj1;
    obj1.data = 10;

    // Using the copy constructor to create 'obj2' as a copy of 'obj1'
    MyClass obj2(obj1);

    // Now 'obj2' contains a copy of 'obj1'
    cout << "obj2.data: " << obj2.data << endl;  // Output: obj2.data: 10

    return 0;
}

8) How is Modularity introduced in C++?

Modularity in C++ is introduced through several key concepts and language features that allow you to break down a program into smaller, manageable, and reusable parts. This makes the code easier to understand, maintain, and extend. Here are the primary ways modularity is achieved in C++:

  • Functions: Encapsulate code blocks for reuse.

  • Classes and Objects: Encapsulate data and related functions.

  • Namespaces: Group related entities to avoid name conflicts.

  • Header and Implementation Files: Separate interface from implementation.

  • Modules (C++20): Provide a modern way to manage dependencies and improve build times.

  • Standard and Custom Libraries: Enable code reuse across projects.

A) Functions:-

#include <iostream>

void printMessage() {
    std::cout << "Hello, World!" << std::endl;
}

int main() {
    printMessage();  // Function call
    return 0;
}

B) Classes & Objects:-

Classes enable object-oriented programming by allowing you to define data structures and the operations that can be performed on them. They encapsulate data and functions together.

#include <iostream>

class Rectangle {
public:
    int width, height;

    int getArea() {
        return width * height;
    }
};

int main() {
    Rectangle rect;
    rect.width = 10;
    rect.height = 5;
    std::cout << "Area: " << rect.getArea() << std::endl;
    return 0;
}

C) Namespaces:-

Namespaces allow you to group related classes, functions, and variables together, reducing name conflicts and enhancing code organization.

#include <iostream>

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

int main() {
    std::cout << "Sum: " << Math::add(3, 4) << std::endl;
    return 0;
}

D) Header and Implementation Files:-

Using header files (.h or .hpp) and implementation files (.cpp), you can separate the interface of your classes and functions from their implementation. This promotes modularity and code reuse.

Header File (example.h)

#ifndef EXAMPLE_H
#define EXAMPLE_H

class Example {
public:
    void display();
};

#endif // EXAMPLE_H

Implementation File (example.cpp)

#include <iostream>
#include "example.h"

void Example::display() {
    std::cout << "Example display function" << std::endl;
}

Main File (main.cpp)

#include "example.h"

int main() {
    Example ex;
    ex.display();
    return 0;
}

E) Modules:-

C++20 introduces modules, which provide a more efficient and robust way to manage dependencies and build systems compared to traditional header files. Modules can significantly improve compile times and encapsulation.

F) Standard Library and Custom Libraries:-

Using the C++ Standard Library and creating custom libraries, you can reuse code across different projects. Libraries encapsulate functionality in a modular way.

ย