Class Template Inheritance and Polymorphism

Introduction to Class Templates in C++

Class templates in C++ allow developers to create generic classes that can work with multiple data types. This approach enables code reuse and flexibility, as a single class can be defined for different types without requiring separate implementations. The concept of class templates is foundational to C++'s ability to handle polymorphism and inheritance in a generic context.

Inheritance in Class Templates

Class templates can inherit from other class templates, enabling a form of hierarchical generic programming. For instance, a List template can inherit from a Container template, allowing the List class to leverage the functionality of the Container class while being specialized for specific data types. This inheritance mechanism is similar to traditional inheritance but operates within the generic context of templates.

Example: Template Inheritance

template <typename T>
class Container {
public:
    T data;
    void display() const { std::cout << data << std::endl; }
};

template <typename T, typename U>
class List : public Container<T> {
public:
    void add(U value) {
        data = value;
    }
};

int main() {
    List<int, double> myList;
    myList.add(42.5);
    myList.display();
    return 0;
}

In this example, the List template inherits from Container<T>, allowing it to use the Container class's functionality while being specialized for int and double. The add method demonstrates how a template can be extended with additional behavior.

Polymorphism in Class Templates

Polymorphism in class templates enables different types to share the same interface, facilitating flexible and reusable code. Templates can be used with multiple types, and their methods can be defined in a way that supports polymorphic behavior, even when the types are generic.

Example: Polymorphic Template Classes

template <typename T>
class Shape {
public:
    virtual void draw() const = 0;
    virtual ~Shape() = default;
};

template <typename T>
class Circle : public Shape<T> {
public:
    void draw() const override {
        std::cout << "Drawing a circle of type " << typeid(T).name() << std::endl;
    }
};

template <typename T>
class Square : public Shape<T> {
public:
    void draw() const override {
        std::cout << "Drawing a square of type " << typeid(T).name() << std::endl;
    }
};

int main() {
    Shape<int> *shape1 = new Circle<int>();
    Shape<double> *shape2 = new Square<double>();
    shape1->draw();
    shape2->draw();
    return 0;
}

Here, the Shape template defines a generic interface, and Circle and Square are specialized classes that inherit from Shape<T>. The draw method is overridden in each class to provide specific behavior, demonstrating how templates can support polymorphic operations.

Advanced Concepts: Template Specialization and Virtual Functions

Class templates can be specialized to handle specific data types, and their methods can be virtual to support polymorphic behavior. This combination allows for flexible and efficient code that can adapt to different types while maintaining a unified interface.

Example: Specialized Templates with Virtual Functions

template <typename T>
class Vector {
public:
    virtual void print() const = 0;
    virtual ~Vector() = default;
};

template <typename T>
class Vector<int> : public Vector<T> {
public:
    void print() const override {
        std::cout << "Int vector: " << static_cast<int>(T::value) << std::endl;
    }
};

template <typename T>
class Vector<double> : public Vector<T> {
public:
    void print() const override {
        std::cout << "Double vector: " << static_cast<double>(T::value) << std::endl;
    }
};

int main() {
    Vector<int> *vec1 = new Vector<int>();
    Vector<double> *vec2 = new Vector<double>();
    vec1->print();
    vec2->print();
    return 0;
}

In this example, Vector is a template class with virtual methods, and Vector<int> and Vector<double> are specialized classes that inherit from Vector<T>. The print method is overridden in each specialization to provide specific behavior, showcasing how templates can be used with virtual functions to support polymorphism.

Conclusion

Class templates in C++ provide a powerful mechanism for creating generic, reusable, and flexible code. By leveraging inheritance and polymorphism, developers can create interfaces that work with multiple types while maintaining a unified structure. The ability to inherit from other templates and override virtual methods enables efficient and scalable solutions, making class templates a cornerstone of modern C++ programming.