C++ pure virtual methods
Asked Answered
E

3

5

Consider this demo program:

#include <stdio.h>

class Base
{
public:
    virtual int f(int) =0;
    virtual int f(){ return f(0); }

    virtual ~Base(){ }
};

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }
};

int main(void)
{
    Derived obj;
    printf("%d\n", obj.f(1));  // This works, and returns 11
    printf("%d\n", obj.f());   // Adding this line gives me the error listed below
}

Which gives me the following compilation error:

virtualfunc.cpp: In function ‘int main()’:
virtualfunc.cpp:25:26: error: no matching function for call to ‘Derived::f()’
virtualfunc.cpp:15:9: note: candidate is: virtual int Derived::f(int)

My hope was that a call to obj.f() would result in a call to Base::obj.f() since the derived class doesn't define it, which would then result in a call to Derived::obj.f(0) per the definition in class Base.

What am I doing wrong here? Is there a way to accomplish this? Specifically, I'd like the call to obj.f() to return 10.

(Also please note that I realize I could use a default argument to solve this, but this code is simply a concise example of my issue, so please don't tell me to use default arguments.)

Thanks.

Escalera answered 3/6, 2011 at 22:0 Comment(7)
The f function in Derived hides the other functions, defined in Base. That's why you get this errorSangsanger
dupe of #586413Big
@Kiril Kirov, You win -- if you want to answer this, I'll mark it as correct. Explicitly adding using Base::f; in the Derived class definition fixed it. Thanks!Escalera
@raj -- Yes it appears to be; I apologize. I actually sifted through 20 or so questions that didn't answer mine and didn't come across this one.Escalera
@Escalera - I'm glad, that I helped. I added my answer (:Sangsanger
Also note that this FAQ addresses this exact issue, sadly I didn't get that warning so I wasn't able to find it.Escalera
@Escalera - Is there any reason why you are declaring base class member functions as virtual here ? Or is it just a future proof where the base class pointer points to the derived type situation ?Grandmamma
S
3

The reason is, that the defined f (in Derived ) hides the f functions from the Base class. The solution is to add using. Like this:

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

//  vvvvvvvvvvvvvv
    using Base::f;
};
Sangsanger answered 3/6, 2011 at 22:9 Comment(0)
S
8

The issue you're running into is orthogonal to pure virtual functions and has to do with how C++ does name resolution in class hierarchies.

When you write

obj.f();

C++ tries to look for a function named f so it knows what to call. Since obj is of type Derived, it starts inside of Derived and looks for a function called f. It ends up finding Derived::f(int), and even though this function takes an argument, C++ thinks this is the method you're trying to call and thus stops looking. The compiler then notices that you're trying to invoke it with no parameters, giving you the error about the function call.

To fix this, you need to tell the C++ compiler that it also needs to try looking for the function Base::f(), which is contained in the base class. To do this, you can change your definition of Derived as follows:

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

    using Base::f;
};

This line using Base::f tells C++ that it should treat functions in Base named f as though they are part of Derived. That way, when the compiler tries looking up a function named f, it finds both Derived::f(int) and Base::f(). The call will then succeed because the compiler can figure out that you're trying to call Base::f() with the code that you've listed.

Hope this helps!

Swingle answered 3/6, 2011 at 22:7 Comment(0)
C
3

The definition of f(int) in the derived class hides the name of Base::f which you didn't override. All you need to do is to unhide this by writing using Base::f;in the derived class:

class Derived : public Base
{
public:

    using Base::f;   //note this line!

    int f(int i)
    {
        return (10 + i);
    }
};
Cowherd answered 3/6, 2011 at 22:8 Comment(2)
@Mahesh: This is nothing to do with virtual mechanism, because he is using object of derived type.Cowherd
I don't see any specific use of virtual here.Grandmamma
S
3

The reason is, that the defined f (in Derived ) hides the f functions from the Base class. The solution is to add using. Like this:

class Derived : public Base
{
public:
    int f(int i)
    {
        return (10 + i);
    }

//  vvvvvvvvvvvvvv
    using Base::f;
};
Sangsanger answered 3/6, 2011 at 22:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.