Override template member in interface

Is it possible to declare some type of base class with template methods that I can override in derived classes? The following example:

#include <iostream>
#include <stdexcept>
#include <string>

class Base
{
public:
    template<typename T>
    std::string method() { return "Base"; }
};

class Derived : public Base
{
public:
    template<typename T>
    std::string method() override { return "Derived"; }
};

int main()
{
    Base *b = new Derived();
    std::cout << b->method<bool>() << std::endl;
    return 0;
}

I would expect Derivedas a conclusion, but that Base. I assume that it is necessary to create a template wrapper class that receives the implementation class as a template parameter. But I want to make sure.

+6
source share
4 answers

1) Your functions must be virtual in order to be polymorphic

2) POI ( ? vtable- ?). - , - .

:

+7

. " " :

#include <iostream>
#include <stdexcept>
#include <string>

template<typename D>
class Base
{
    template<typename T>
    std::string _method() { return "Base"; }
public:

    template<typename T>
    std::string method()
    {
       return static_cast<D&>(*this).template _method<T>();
    }
};

class Derived : public Base<Derived>
{
    friend class Base<Derived>;

    template<typename T>
    std::string _method() { return "Derived"; }
public:
    //...
};

int main()
{
    Base<Derived> *b = new Derived();
    std::cout << b->method<bool>() << std::endl;
    return 0;
}

method - , _method - . , _method Base.

, Base Base<Derived>, , . Base*.

, const static_cast<D&> static_cast<const D&>. , rvalue-reference (&&) static_cast<D&&>.

+3

, , , std::function:

class Base {
  public:
    Base() {
      virtualFunction = [] () -> string { return {"Base"}; };
    }
    template <class T> string do_smth() { return virtualFunction(); }
    function<string()> virtualFunction;
};
class Derived : public Base {
  public:
    Derived() {
      virtualFunction = [] () -> string { return {"Derived"}; };
    }
};

int main() {
  auto ptr = unique_ptr<Base>(new Derived);
  cout << ptr->do_smth<bool>() << endl;
}

"". , , , , .

+2

, . :

( , ):

class Base
{
    template <class T>
    virtual T func(T a, T b) {};
}

class Derived
{
    template <class T>
    T func(T a, T b) { return a + b; };
}

int main()
{
    Base* obj = new Derived();
    std::cout << obj->func(1, 2) << obj->func(std::string("Hello"), std::string("World")) << obj->func(0.2, 0.1);
    return 0;
}

( 3HelloWorld0.3):

class BaseType
{
public:
    virtual BaseType* add(BaseType* b) { return {}; };
};

template <class T>
class Type : public BaseType
{
public:
    Type(T t) : value(t) {};
    BaseType* add(BaseType* b)
    {
        Type<T>* a = new Type<T>(value + ((Type<T>*)b)->value);
        return a;
    };

    T getValue() { return value; };
private:
    T value;
};

class Base
{
public:
    virtual BaseType* function(BaseType* a, BaseType* b) { return {}; };
    template <class T>
    T func(T a, T b)
    {
        BaseType* argA = new Type<T>(a);
        BaseType* argB = new Type<T>(b);
        BaseType* value = this->function(argA, argB);
        T result = ((Type<T>*)value)->getValue();
        delete argA;
        delete argB;
        delete value;
        return result;
    };
};

class Derived : public Base
{
public:
    BaseType* function(BaseType* a, BaseType* b)
    {
        return a->add(b);
    };
};

int main()
{
    Base* obj = new Derived();
    std::cout << obj->func(1, 2) << obj->func(std::string("Hello"), std::string("World")) << obj->func(0.2, 0.1);
    return 0;
}

BaseType , . (, , ), , . , , .

Type - , Derived. , Type<int>. , BaseType. , BaseType, .

function - , . BaseType . Base , func. function T Type<T>. Base function, .

0

Source: https://habr.com/ru/post/1531906/


All Articles