C++ Questions

Polymorphism with dynamic cast and type id:

#include <iostream>
#include <typeinfo>

class Base {
public:
    virtual ~Base() = default; // Make Base polymorphic for dynamic_cast
    virtual void print() const {
        std::cout << "This is Base class" << std::endl;
    }
};

class Derived1 : public Base {
public:
    void print() const override {
        std::cout << "This is Derived1 class" << std::endl;
    }
};

class Derived2 : public Base {
public:
    void print() const override {
        std::cout << "This is Derived2 class" << std::endl;
    }
};

void checkTypeAndCast(Base* basePtr) {
    // Check if basePtr is of type Derived1
    if (Derived1* d1 = dynamic_cast<Derived1*>(basePtr)) {
        std::cout << "basePtr is of type Derived1" << std::endl;
        d1->print();
    }
    // Check if basePtr is of type Derived2
    else if (Derived2* d2 = dynamic_cast<Derived2*>(basePtr)) {
        std::cout << "basePtr is of type Derived2" << std::endl;
        d2->print();
    }
    // If neither, then it is a Base or incompatible type
    else {
        std::cout << "basePtr is of type Base or unknown type" << std::endl;
        basePtr->print();
    }

    // Optionally, show RTTI type info for additional verification
    std::cout << "Type info: " << typeid(*basePtr).name() << std::endl;
}

int main() {
    // Dynamically allocate objects
    Base* ptrBase = new Base();
    Base* ptrBase1 = new Derived1();
    Base* ptrBase2 = new Derived2();

    // Perform type checks and casts
    checkTypeAndCast(ptrBase);       // Should identify as Base
    checkTypeAndCast(ptrBase1);    // Should identify as Derived1
    checkTypeAndCast(ptrBase2);    // Should identify as Derived2

    // Clean up dynamically allocated memory
    delete ptrBase;
    delete ptrBase1;
    delete ptrBase2;

    return 0;
}

Why virtual destructor?

#include<iostream>
class Base {
public:
    virtual ~Base() { // Virtual destructor, toggle and check
        std::cout << "Base destructor called" << std::endl;
    }
};

class Derived : public Base {
public:
    ~Derived() { // Destructor for Derived
        std::cout << "Derived destructor called" << std::endl;
    }
};

void test() {
    Base* obj = new Derived();
    delete obj; // Calls both Derived and Base destructors
}


int main()
{
test();
    return 0;
}
/*
Derived destructor called - this will be skipped if virtual is skipped
Base destructor called
*/