Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Virtual function implemented in base class not being found by compiler

Tags:

I've got a situation where it seems like the compiler isn't finding the base class definition/implementation of a virtual function with the same name as another member function.

struct One {};  struct Two {};  struct Base {     virtual void func( One & );     virtual void func( Two & ) = 0; };  struct Derived : public Base {     virtual void func( Two & ); };  void Base::func( One & ) {}  void Derived::func( Two & ) {}  // elsewhere void this_fails_to_compile() {     One one;     Derived d;     d.func( one ); } 

I'm using Visual C++ 2008. The error message is:

error C2664: 'Derived::func' : cannot convert parameter 1 from 'One' to 'Two &'

I would have thought that the type based dispatch would work and call the defined base class function. If I add a Derived::func( One & ) it does compile and get called correctly, but in my situation, that version of the function can be done in the base class and usually derived classes don't need to implement it themselves. I'm currently working around it by putting a differently named, non-virtual function in the base class that forwards the call to function causing the problem:

// not virtual, although I don't think that matters void Base::work_around( One & one ) {     func( one ); } 

That works but is obviously less than ideal.

What inheritance and/or name-hiding rule am I missing here?

like image 248
Kurt Hutchinson Avatar asked Sep 09 '10 15:09

Kurt Hutchinson


People also ask

How does the compiler detect virtual functions?

Late binding or Dynamic linkage Therefore compiler determines the type of object at runtime, and then binds the function call. Virtual functions must be members of some class. Virtual functions cannot be static members. They are accessed through object pointers.

How do you find the virtual function in base class?

Virtual functions should be accessed using pointer or reference of base class type to achieve runtime polymorphism. The prototype of virtual functions should be the same in the base as well as derived class. They are always defined in the base class and overridden in a derived class.

Can pure virtual function have implement in base class?

In our discussion __purecall , we saw that you can declare a pure virtual function with the = 0 syntax, and if you try to call one of these functions from the base class, you will get the dreaded R6025 – pure virtual function call error.

At which conditions does virtual base class need to be implemented?

Need for Virtual Base Class in C++Only one copy of its data members is shared by all the base classes that use the virtual base class. If a virtual base class is not used, then all the derived classes will get duplicated data members. In this case, the compiler cannot decide which one to execute.


2 Answers

You are hiding the method in the derived class. The simplest solution is to add a using declaration to the derived class.

struct Derived : public Base {     using Base::func;     virtual void func( Two & ); }; 

The issue is that when the compiler tries to lookup the func identifier in the call d.func(one) it has to do that from Derived upwards, but it will stop in the first context where it finds the func identifier, which in this case it is Derived::func. No further lookup is performed and the compiler was seeing only the Derived::func( Two& ).

By adding the using Base::func; directive, when the compiler sees the Derived definition it brings all of Base::func declarations into scope, and it will find that there is a Base::func( One & ) that was not overridden in Derived.

Note also that if you were calling through a reference to Base, then the compiler would find both overloads of func and would dispatch appropriately each one to the final overrider.

Derived d; Base & b = d; b.func( one ); // ok even without the 'using Base::func;' directive 
like image 127
David Rodríguez - dribeas Avatar answered Sep 23 '22 00:09

David Rodríguez - dribeas


You hide func(One&) function in Derived. You could use fully qualified name:

d.Base::func( one ); 
like image 37
Kirill V. Lyadvinsky Avatar answered Sep 21 '22 00:09

Kirill V. Lyadvinsky