JalalJaberi
JalalJaberi

Reputation: 2617

C++ Compiler (cl) does not see parent virtual method with same child method name

I have a C++ code, using inheritance and function overriding at the same time, here is the code:

#include <iostream>
#include <string>

using namespace std;

class Parent
{
    protected:
        virtual void G() const = 0;
    public:
        virtual void G(const string& s) const final { G(); }
};

class Child : public Parent
{
    protected:
        virtual void G() const override { cout<<"Child G"; }
};

int main()
{
    Child *c = new Child();
    c->G("test");
    return 0;
}

When compile, I got error: Child::G: function does not take 1 arguments. But when I use Parent pointer like this:

Parent *c = new Child();

It works. Alternatively if I change public G method's name, it works too.

What is wrong about using same name (G) for both methods?

Upvotes: 1

Views: 68

Answers (2)

alter_igel
alter_igel

Reputation: 7202

The fix for this is indeed to introduce the Parent's method into the scope of the Child class with a using declaration, as @Jans kindly points out. As to why this is the case is simply a matter of how the compiler searches through scopes when searching for a method to match your function call. A break down of what's happening is as follows:

  • in Child *c = new Child(); c->G("test");, the compiler sees a call to some method G on an object of type Child. It then searches the scope of Child to look for a match.
  • The compiler, when exploring the scope of Child, sees only Child::G() const. It does not see Parent::G(const std::string&) const, which even though you want it to be included via inheritance, is in a different scope. In a sense, Child::G is shadowing Parent::G. Without a candidate match, the compiler would have kept searching into the Parent scope.
  • The compiler thus is happy having found Child::G. However, this is a function accepting no arguments, and you tried to call it with "test". The function call then fails because of a mismatch in the parameters.

As stated, you need to bring Parent::G into the same scope as Child::G for overloading to happen as intended, with using Parent::G inside the body of Child.

Source: https://isocpp.org/wiki/faq/strange-inheritance#overload-derived

Upvotes: 1

Jans
Jans

Reputation: 11250

You need to introduce the parent member into the child with a using declaration:

class Child : public Parent
{
    protected:
        virtual void G() const override { cout<<"Child G"; }
    public:
        using Parent::G;
};

Upvotes: 3

Related Questions