2017-02-14 2 views
0

Le code suivantfonction virtuelle privée de la base est cachée par la fonction virtuelle privée de dérivé

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; 
} 

compilé avec g++ -Woverloaded-virtual produit ledit avertissement:

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 {} 
    ^

Je ne comprends pas ce qui est caché ici. De la portée de C il n'y a qu'une seule surcharge possible à f car B::f(int) est privé au sein de C.

De la portée de B, il y en a deux, mais les deux sont explicitement nommés B.

Répondre

1

mentionnant la GCC manual:

-Woverloaded-virtual (C++ et Objective-C++ uniquement) avertir si une déclaration de fonction cache fonctions virtuelles à partir d'une classe de base. Par exemple, dans:

struct A { 
    virtual void f(); 
}; 

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

la version de classe A de f est caché dans B et code comme:

B* b; 
b->f(); 

ne parvient pas à compiler.

4

L'avertissement vous indique que la fonction C::f(float) cache B::f(int), et c'est parce it does. Les spécificateurs d'accès n'affectent pas la surcharge, donc le fait que B::f(int) soit privé n'a pas d'importance. Même si B::f(int) était public, il ne serait pas pris en compte pour la résolution de surcharge, et c'est ce que l'on appelle le "masquage".

+0

Mais à quoi sert cet avertissement? Cela m'avertit de quelque chose qui, en fait, ne s'applique pas à ma situation. Comment puis-je m'en débarrasser (autre que le commutateur '#pragma diagnostics')? – TFM

+0

@TFM, 'C * c = nouveau C; c-> f (int {}); 'ici, f (float) sera choisi pour l'envoi. mais ici 'B * b = c; b -> f (int {}) 'f signifie f (int). par exemple, si vous avez la hiérarchie suivante: struct A {virtual void f (int), f (float); } structure B: A {void f (float);}; structure C: B {void f (int), f (float);}; 'alors via l'iface de B vous pouvez envoyer seulement f (float), sauf si vous qualifiez explicitement le nom de f avec A (b_iface-> A :: f (int {})). –

+0

@ GreenTree Je comprends ce que cet avertissement signifie dans une situation où cela a du sens. J'essaie de comprendre ses implications dans ma situation. – TFM

1

Je ne comprends pas ce qui est caché ici. De la portée de C il y a seulement une surcharge possible à f comme B::f(int) est private au sein de C.

La recherche de nom et la résolution se produisent avant que les règles d'accès ne soient appliquées.

B::f(int) est masqué par C::f(float) lorsque le nom f est recherché à partir d'un objet C. C'est ce que le compilateur vous avertit.