kod kristoff
kod kristoff

Reputation: 89

virtual method not seen in implementation

i am currently working on a C++ project where i have an abstract interface that is implemented later on. The interface also has a implemented method which my implementation doesn't override. My problem is that when using my implementation, the compiler(MSVC) doesn't see the interface method. What causes this, and how can i resolve it?

Here comes the code.

#include <string>
#include <vector>
using std::string;

class A
{
    public:
    string name;
};

class interface
{ 
public:
    virtual int num_foo() = 0;
    virtual A* foo(int) = 0;
    virtual A* foo(string &name){
        for ( int i(0); i < num_foo(); i++)
            if ( foo(i)->name == name )
                return foo(i);
        return 0;
    }
};

class implementation : public interface
{
public:
    virtual int num_foo() { return m_foos.size(); }
    virtual A* foo(int i) { 
        //check range 
        return &m_foos[i];
    }
    std::vector<A> m_foos;
};

int main(...)
{
    implementation impl;
    // impl is properly initialized here

    string name( "bar" );
    // here comes my problem, the MSVC compiler doesn't see foo(string &name)
    // and gives an error
    A *a = impl.foo( name );
}

Upvotes: 1

Views: 200

Answers (4)

TBBle
TBBle

Reputation: 1466

This is only an issue because you're accessing the implementation interface, which does have a foo member, as noted already in the answer by @charles-bailey.

Semantically, what you're trying to call is the interface method foo, so you probably should actually call that:

int main()
{
    implementation impl;
    string name( "bar" );
    interface& interf = impl;
    A *a = interf.foo( name );
    A *b = interf.foo( 4 );
}

This would also allow you to implement the Non-Virtual Interface idiom, by making implementation::foo private. You'd still fail if you try to call impl.foo directly, but you'd fail for all argument types, with the same error.

(I know this question is old, but NVI is older...)

Upvotes: 0

KV Prajapati
KV Prajapati

Reputation: 94635

class implementation : public interface{
    public:
       using interface::foo;
       int num_foo() { return m_foos.size(); }
       A& foo(int i)
       {   //check range
           return m_ones[i];
       }
       vector<A> m_foos;
       vector<A> m_ones;
};

Upvotes: 1

CB Bailey
CB Bailey

Reputation: 791481

Name resolution happens before overload resolution. In impl.foo( name ), then compiler looks at the implementation class and finds only virtual A& foo(int i). It does not look at the base class as it has found a function with the right name.

To correct this use can add a using interface::foo declaration to the derived class to pull all of the base versions of foo into the derived class for the purposes of overload resolution. Usually, I'd prefer to avoid overloaded functions and I'd probably give the variants of foo different function names.

(Other errors are that you don't define string, vector or m_ones; you attempt to use -> instead of . on a reference and you attempt to return 0 in a function returning a reference to an A.)

Upvotes: 5

Martin v. L&#246;wis
Martin v. L&#246;wis

Reputation: 127447

To re-publish base methods (such as foo(string)) in a subclass for overloading, add

  using interface::foo;

into class implementation.

Upvotes: 3

Related Questions