Overloading mess: No matching function for call

Hi.
I wrote a code similar to this one, for a wrapper application that I needed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>

using namespace std;

class Client
{
public:
    void setEndpoint(const string& s) throw() { a_endpoint = s; setEndpoint(); }

protected:
    virtual void setEndpoint() throw() = 0;

    string a_endpoint;
};

class NotifyClient : public Client
{
public:
    const char* endpoint;

private:
    void setEndpoint() throw() { endpoint = a_endpoint.c_str(); }
};


int main()
{
    NotifyClient client;
    string url("http://www.google.com");
    client.setEndpoint( url ); 

    return 0;
}


But I'm getting this compile error with g++:

inheritanceTopic.cc:30: error: no matching function for call to `NotifyClient::setEndpoint(std::string&)'
inheritanceTopic.cc:22: note: candidates are: virtual void NotifyClient::setEndpoint()

If I change the line,

client.setEndpoint( url );

by

client.Client::setEndpoint( url );

it works.

I'm wondering why is it. I guess it has something to do with function
overloading and the compiler, because if I change names, it works too.

Can anyone give me a better explanation?
I would like to use the same name in the functions, but I don't like
the style of:

 
    client.Client::setEndpoint( url );


pretty ugly....

Thanks in advance,
Tomas.
Last edited on
Because of polymorphism.

When you declare a virtual method in base class and inherit it to derived class expecting its virtual method needs to be "defined" (nothing yet provided in the base class as it is a pure virtual method), then you would be declaring and accessing the base class through a base class type pointer.

Your base class is an abstract class (since it has a pure virtual method) and can not instantiated by itself.
You derived class depends upon the defintion provided by base for setEndPoint(const string &).

To instantiate base and derived parts and to be active in your object,
you should access it as a polymorphic class but not just normal class.
Hence you declare a pointer of base type and initialize it with the derived which has definition for placeholder (ie setEndPoint()) provided by base and access it right through the object that has all the definitions for the methods.

The revised code would look like:

1
2
3
4
5
6
    Client * pClient;   // add this line
    // NotifyClient client;  remove this as it is instantiated below
    pClient = new NotifyClient;  // create an object of NotifyClient and let pClient (base type) points to it
    string url("http://www.google.com");
    //client.setEndpoint( url );    //change it to be below
    pClient->setEndPoint( url );



Try it now. It should work as you desire.

Good luck :)
Last edited on
@satm2008 that was my first guess - but I think the problem is that functions in a derived class hides functions in the bass class of the same name - although virtual functions can be overriden by the derived class
That is why he cannot 'see' the setEndpoint(string&) function from the NotifyClient class because it is hidden by the setEndpoint() function - which is why he has to useclient.Client::setEndpoint( url );
Right.
It can be found in TC++PL Special Edition, page 392,
section 15.2.2: Inheritance and Using-Declarations,
with a longer and extended explanation with multiple inheritance.

Basically, "Overload resolution is not applied across different class scopes".

So as long as,

void setEndpoint() hides void setEndpoint(const string&)

I guess I'll have to live with:

client.Client::setEndpoint( url );

or change the name of the function.
Last edited on
No, it does not seem to be so.

Since the function signatures are different, and the call is with a string parameter, it would look for a match which is defined and available from the base part.
But the object is a polymorphic class but NOT instantiated to be so hence the object is created as regular as with no virtual table nor virtual pointer to identify the method to be called (from base or derived). It is unknown or conflicting in runtime.

So obviously the compiler would say, I can not see it and I dont know what to call for.

And I would not suggest you to see it using client.Client::setEndPoint( url ) with class resolution operator either. When it is defined as polymorphic, access it to be so, that is what my recommendation.

Hope this clarifies my point. Good luck :)
Last edited on
I don't understand completely your statement:

But the object is a polymorphic class but NOT instantiated to be so hence the object is created as regular as with no virtual table nor virtual pointer to identify the method to be called (from base or derived).


It is not clear to me. I thought the virtual table is always created if exists one virtual function:

http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.3

Maybe not here because is pure virtual?

Anyway, I'm happy with the scope explanation as is stated in TC++PL.

It is also possible to insert:

1
2
public: 
    using Client::setEndpoint; 


into class NotifyClient, that makes both functions visible.
Yes, the virtual table is created if there is at least one virtual function in a class.
But you should also access it as a virtual method or polymorphic object.

What I meant is that your declaration of NotifyClient (derived) object would not be accessed as a polymorphic as you are not accessing it through the base class type pointer.



Topic archived. No new replies allowed.