0

The following code

class A
{
public:
    void g(int x)
    {
        f(x);
    }

protected:
    virtual void f(int) = 0;
};

class B: public A
{
protected:
    virtual void f(float) = 0;

private:
    void f(int x) override final
    {
        f(float(x));
    }
};

class C: public B
{
private:
    void f(float) override final {}
};

int
main()
{
    C c;
    c.g(1);

    return 0;
}

compiled with g++ -Woverloaded-virtual produces said warning:

x.cc:19:7: warning: ‘virtual void B::f(int)’ was hidden [-Woverloaded-virtual]
  void f(int x) override final
       ^
x.cc:28:7: warning:   by ‘virtual void C::f(float)’ [-Woverloaded-virtual]
  void f(float) override final {}
       ^

I do not understand what is being hidden here. From the scope of C there is only one possible overload to f as B::f(int) is private within C.

From the scope of B there are two, but both are explicitly named inside B.

jotik
  • 17,044
  • 13
  • 58
  • 123
TFM
  • 717
  • 6
  • 21

3 Answers3

4

The warning is telling you that the function C::f(float) hides B::f(int), and that's because it does. Access specifiers don't affect overloading, so the fact that B::f(int) is private doesn't matter. Even if B::f(int) was public, it wouldn't be considered for overload resolution, and that's what "hiding" refers to.

Volodymyr Boiko
  • 1,533
  • 15
  • 29
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • But what is the point of this warning then? It warns me about something that in fact does not apply to my situation. How can I get rid of it (other then `#pragma diagnostics` switch)? – TFM Feb 15 '17 at 01:01
  • @TFM, `C*c=new C; c->f(int{});` here f(float) will be chosen for dispatching. but here `B * b = c ; b -> f( int{} )` f means f(int). for example, if you have following hierarchy `struct A{ virtual void f(int),f(float); }; struct B:A{void f(float);}; struct C:B{void f(int),f(float);};` then via B's iface you can dispatch only f(float), unless you explicitly qualify f's name with A's (b_iface->A::f(int{})). – Volodymyr Boiko Feb 15 '17 at 02:16
  • @GreenTree I understand what this warning means in a situation in which it actually makes sense. I'm trying to understand its implications in my situation. – TFM Feb 15 '17 at 08:16
  • @TFM, it makes sense from point of language. "From the scope of C there is only one possible overload to f as B::f(int) is private within C". this wording is not right. it will be found if C will be defined as struct C : B { } obj ; obj.f( int{} ) ;.this code should not compile because B::f( int ) is private, but not because it's not visible. privatness of f( int ) doesn't affect overload resolution. that is why struct { void f ( float ) { } private : void f ( int ) { } } obj ; obj.f( int{} ) ; should not compile - f founded, but it's private. – Volodymyr Boiko Feb 15 '17 at 09:03
1

Quoting the GCC manual:

-Woverloaded-virtual (C++ and Objective-C++ only) Warn when a function declaration hides virtual functions from a base class. For example, in:

struct A {
    virtual void f();
};

struct B: public A {
    void f(int);
};

the A class version of f is hidden in B, and code like:

B* b;
b->f();

fails to compile.

jotik
  • 17,044
  • 13
  • 58
  • 123
1

I do not understand what is being hidden here. From the scope of C there is only one possible overload to f as B::f(int) is private within C.

Name lookup and resolution happens before access rules are applied.

B::f(int) is hidden by C::f(float) when the name f is looked up from a C object. That's what the compiler is warning you about.

R Sahu
  • 204,454
  • 14
  • 159
  • 270