简体   繁体   中英

Why can't I call a templated method from a derived class instance in C++?

Please consider these types:

struct X
{
    static std::string fullyQualifiedName();
};


struct A
{
    template <class T> void foo()
    {
        return foo(T::fullyQualifiedName());
    }

protected:
    virtual void foo(const std::string& name) = 0;
};


struct B : public A
{
protected:
    void foo(const std::string& name);
};

I have a pointer to an instance of B, I'm trying to invoke the templated version of foo like so:

b->foo< X >();

The compiler is complaining: 'X' : illegal use of this type as an expression.

On the other hand, this code's perfectly ok:

A* a = b;
a->foo< X >();

Hence my question.

The problem you are facing is called hiding. Basically the lookup rules in the language will start in the most derived type and work their way back up until it finds the appropriate symbol. In your case it will stop while looking at the B class as it finds void B::foo(const std::string& name) . At that level, the only potential overload that it will consider is the one it is seeing.

To avoid hiding you can bring all the other overloads you can add a using declaration:

struct B : A{
   using A::foo;
   void foo( const std::string & name );
};

The difference is that lookup will work up the hierarchy until it finds the first overload, which is again at B level, but because of the using directive, it will also consider any overload available in A .

Alternatively, you can leave the symbol hidden and force dispatch to the exact class by qualifying the call (note that this has the side effect of disabling dynamic dispatch, which is not a problem here, but could be if the overload to use is virtual):

b->A::foo<X>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM