Templatized Virtual function

后端 未结 4 1259
渐次进展
渐次进展 2020-12-05 21:40

We know that C++ doesn\'t allow templated virtual function in a class. Anyone understands why such restriction?

4条回答
  •  佛祖请我去吃肉
    2020-12-05 22:24

    The other answers have already mentionned that virtual functions are usually handled in C++ by having in the object a pointer (the vptr) to a table. This table (vtable) contains pointer to the functions to use for the virtual members as well as some other things.

    The other part of the explanation is that templates are handled in C++ by code expansion. This allow explicit specialization.

    Now, some languages mandate (Eiffel -- I think it is also the case of Java and C#, but my knowledge of them is not good enough to be authoritative) or allow (Ada) an shared handling of genericity, don't have explicit specialization, but would allow virtual template function, putting template in libraries and could reduce the code size.

    You can get the effect of shared genericity by using a technique called type erasure. This is doing manually what compilers for shared genericity language are doing (well, at least some of them, depending on the language, other implementation techniques could be possible). Here is a (silly) example:

    #include 
    #include 
    
    #ifdef NOT_CPP
    class C
    {
    public:
        virtual template int getAnInt(T const& v) {
            return getint(v);
        }
    };
    #else
    class IntGetterBase
    {
    public:
        virtual int getTheInt() const = 0;
    };
    
    template
    class IntGetter: public IntGetterBase
    {
    public:
        IntGetter(T const& value) : myValue(value) {}
        virtual int getTheInt() const
        {
            return getint(myValue);
        }
    private:
        T const& myValue;
    };
    
    template
    IntGetter makeIntGetter(T const& value)
    {
        return IntGetter(value);
    }
    
    class C
    {
    public:
        virtual int getAnInt(IntGetterBase const& v)
        {
            return v.getTheInt();
        }
    };
    #endif
    
    int getint(double d)
    {
        return static_cast(d);
    }
    
    int getint(char const* s)
    {
        return strlen(s);
    }
    
    int main()
    {
        C c;
        std::cout << c.getAnInt(makeIntGetter(3.141)) + c.getAnInt(makeIntGetter("foo")) << '\n';
        return 0;
    }
    

提交回复
热议问题