Specialized Inheritance

I recently found a case where it was easier to specialize a template instead of real inheritance. Derived classes simply had to implement a pure virtual function and did not have their own members. It was something like:

#include <iostream>

class Interface {
public:
    virtual void calculate() = 0;
    virtual float getResult() = 0;
};

class Base : public Interface {
    float result;
public:
    Base() : result(1) {};
    virtual ~Base() {};

    virtual void calculate();
    virtual float getValue() = 0; // do some very complex calculation here

    float getResult() { return result; }
};

class DerivedA : public Base {
public:
    DerivedA() : Base() {};
    ~DerivedA() {};

    float getValue();
};

class DerivedB : public Base {
public:
    DerivedB() : Base() {};
    ~DerivedB() {};

    float getValue();
};

void Base::calculate() {
    for (int i = 0; i < 10; i++)
        result += getValue();
}

float DerivedA::getValue() {
    return 1;
}

float DerivedB::getValue() {
    return 1.1;
}

int main() {
    Interface * a = new DerivedA();
    a->calculate();

    Interface * b = new DerivedB();
    b->calculate();

    std::cout << "Result A: " << a->getResult() << std::endl;
    std::cout << "Result B: " << b->getResult() << std::endl;

    delete a;
    delete b;
}

This can be written in the form of specialized templates:

#include <iostream>

class Interface {
public:
    virtual void calculate() = 0;
    virtual float getResult() = 0;
};

template<typename T>
class Base : public Interface {
    float result;
public:
    Base() : result(1) {};

    void calculate();
    float getValue(); // do some very complex calculation here

    float getResult() { return result; };
};

typedef Base<int>   DerivedA; // actually int and float are only examples
typedef Base<float> DerivedB; // and may be some much more complex types!

template<typename T>
void Base<T>::calculate() {
    for (int i = 0; i < 10; i++)
        result += getValue();
}

template<typename T>
float Base<T>::getValue() {
    return 0;
}

template<>
float Base<int>::getValue() {
    return 1;
}

template<>
float Base<float>::getValue() {
    return 1.1;
}

int main() {
    Interface * a = new DerivedA();
    a->calculate();

    Interface * b = new DerivedB();
    b->calculate();

    std::cout << "Result A: " << a->getResult() << std::endl;
    std::cout << "Result B: " << b->getResult() << std::endl;

    delete a;
    delete b;
}

Both examples give the same results, I believe that the second one is faster, since no virtual tables need to be evaluated (the getValue () methods can even be built into the second case).

, : ? , ? ? , , . , , - ?

Btw: ?

+4
2

.

  • (.. )

  • : Base , .

, , Base<> (, std::vector<Base<??>>) calculate() ? .

, , : , .

:

+6

DerivedA DerivedB templated , .

void method(Base &base)
{
    // ...
}

, . () :

template<typename T>
void method(Base<T> &base)
{
    // ...
}

() , .

0

All Articles