2010-11-29 23 views
11
class Base 
{ 
    public: void foo(){} 
}; 

class Derived : public Base 
{ 
    private: 
    using Base::foo; 
}; 

int main() 
{ 
    Derived d; 
    d.foo(); 
} 

Le code est-il légal? La déclaration using Base::foo se trouve dans la section privée de la classe dérivée. Donc, l'appel ne devrait pas compiler, ai-je raison?Accès à la fonction de classe de base

+0

Quel compilateur utilisez-vous? –

+0

Vite Falcon .... g ++. – JKS

+0

Vous avez accepté la réponse de @Prasoon Saurav, ce qui est bien. Mais vous devez être conscient que cette méthode, bien que techniquement légale, est obsolète et ne devrait pas être utilisée dans le développement de nouveaux champs. –

Répondre

1

La norme dans la section 11.2/4 dit

A member m is accessible when named in class N if

— m as a member of N is public, or

— m as a member of N is private, and the reference occurs in a member or friend of class N, or

— m as a member of N is protected, and the reference occurs in a member or friend of class N, or in a member or friend of a class P derived from N, where m as a member of P is private or protected, or

there exists a base class B of N that is accessible at the point of reference, and m is accessible when named in class B.

Cependant, la norme indique également que

§11.3/1 "The access of a member of a base class can be changed in the derived class.

Dans votre code d'accès de l'organe foo a été changé dans la classe dérivée. Donc le code ne devrait pas compiler mais this is still an active issue with open status Donc certains compilateurs compilent le code (Comeau et Intel C++) alors que g ++ et MSVC++ (correctement) le rejettent.

+3

Je jure que vous devez avoir mémorisé la norme;) La référence est toujours appréciée. – luke

+4

+1, ceci est correct et corroboré par 7.3.3/15 –

+2

-1 g ++ et msvc en désaccord. et de même le Saint Standard (@prasoon, je déteste vraiment quand les gens évoquent des citations du HS qui apparemment contredisent ce que j'ai déjà écrit! ). si vous venez de lire le paragraphe suivant dans le SH, à savoir le §11.3, il est entièrement consacré aux * déclarations d'accès *, "L'accès d'un membre d'une classe de base peut être modifié dans une classe dérivée ... l'effet est défini pour être équivalent à la déclaration en utilisant 'using' * qualified-id *". Ces déclarations d'accès étaient l'ancienne méthode pré-standard. 'using 'est la façon C98. acclamations & hth., –

5

Droite.

Maintenant la vérification de la réalité & hellip;

MinGW g ++ 4.4.1:

x.cpp: In function 'int main()': x.cpp:3: error: 'void Base::foo()' is inaccessible
x.cpp:15: error: within this context

Visual C++ 10,0:

x.cpp(15) : error C2248: 'Derived::foo' : cannot access private member declared in class 'Derived'
x.cpp(9) : see declaration of 'Derived::foo'
x.cpp(6) : see declaration of 'Derived'

Comeau Online 4.3.10.1:

In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link).
Compiled with C++0x extensions enabled.

Oops. Et Comeau est celui qui a presque toujours raison! Eh bien, éteindre C++ 0x extensions, pour 98 C++/C++ 03:

In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link).
Compiled with C++0x extensions DISabled.

Oops!

Eh bien, vous mine Biggie, comme on dit en Norvège (littéralement traduit en anglais).

J'essaierais de signaler cela à Comeau.

EDIT: puisque Prasoon a également répondu, citant le Saint Standard avec son interprétation de ce qui contredit ce que j'ai écrit ci-dessus, bien, OK, standadeese & hellip;

§11.3/1 "L'accès d'un membre d'une classe de base peut être modifié dans la classe dérivée & hellip;", et ainsi de suite, aussi clair que possible (aucune interprétation requise). Et avec un exemple concret. Et le texte normatif indiquant que cela équivaut à une déclaration using.

Vive & HTH.,

+0

est-ce un bug de comeau ou en g ++? – JKS

+0

@Alf, veuillez voir 7.3.3/15 pour un exemple concret qui * ajuste * les spécificateurs d'accès avec la déclaration using. Existe-t-il deux façons de le faire, ou la norme est-elle ambigieuse (ne serait-ce pas la première fois ou même la millième fois), ou l'une de nos interprétations est-elle incorrecte? –

+0

@John: (1) non cet exemple ne modifie pas l'accès (c'est un exemple d'essayer d'accéder à quelque chose qui est inaccessible); (2) oui, il y a deux façons (une pré-standard et obsolète, et le C++ 98 'using'); et (3) comme Prasoon vous auriez dû lire, au paragraphe suivant, dans votre cas § 7.3.3/16 - même si c'est juste note non-normative. Cheers & hth., –

0

using est une déclaration d'espace de noms dans cet exemple (par opposition à un espace de noms directive). Ce n'est pas une déclaration de méthode, comme vous semblez l'intention de l'utiliser.

La méthode foo() est publique dans la classe Base et est toujours accessible dans la classe Derived.

Vous semblez avoir l'intention de rendre le foo() de la classe Base inaccessible. Bien qu'il puisse y avoir un moyen de le faire (je ne sais pas, je n'ai jamais eu de raison de le tenter), je suggère que cela montre une erreur dans la logique de votre héritage, et vous voudrez peut-être envisager une nouvelle conception Vos classes.

Si votre classe Derived ne va pas se comporter comme une classe Base, il ne devrait pas hériter d'une classe Base.

+1

-1 en utilisant la déclaration using de cette façon rend 'foo' inaccessible par' Derived' –

+0

En maintenant le d/v pendant que nous effaçons cela ... –

+0

Cela semble être clair, donc je remets la dv sur –