Override template member in Interface

后端 未结 4 1947
醉话见心
醉话见心 2021-01-02 00:34

Is it possible to declare some type of base class with template methods which i can override in derived classes? Following example:

#include          


        
4条回答
  •  渐次进展
    2021-01-02 01:12

    I had the same problem, but I actually came up with a working solution. The best way to show the solution is by an example:

    What we want(doesn't work, since you can't have virtual templates):

    class Base
    {
        template 
        virtual T func(T a, T b) {};
    }
    
    class Derived
    {
        template 
        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;
    }
    

    The solution(prints 3HelloWorld0.3):

    class BaseType
    {
    public:
        virtual BaseType* add(BaseType* b) { return {}; };
    };
    
    template 
    class Type : public BaseType
    {
    public:
        Type(T t) : value(t) {};
        BaseType* add(BaseType* b)
        {
            Type* a = new Type(value + ((Type*)b)->value);
            return a;
        };
    
        T getValue() { return value; };
    private:
        T value;
    };
    
    class Base
    {
    public:
        virtual BaseType* function(BaseType* a, BaseType* b) { return {}; };
        template 
        T func(T a, T b)
        {
            BaseType* argA = new Type(a);
            BaseType* argB = new Type(b);
            BaseType* value = this->function(argA, argB);
            T result = ((Type*)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;
    }
    

    We use the BaseType class to represent any datatype or class you would usually use in a template. The members(and possibly operators) you would use in a template are described here with the virtual tag. Note that the pointers are necessary in order to get the polymorphism to work.

    Type is a template class that extends Derived. This actually represents a specific type, for example Type. This class is very important, since it allows us to convert any type into the BaseType. The definition of the members we described described in BaseType are implemented here.

    function is the function we want to override. Instead of using a real template we use pointers to BaseType to represent a typename. The actual template function is in the Base class defined as func. It basically just calls function and converts T to Type. If we now extend from Base and override function, the new overridden function gets called for the derived class.

提交回复
热议问题