C++ access modifiers and 'using' declarations

Started by
23 comments, last by Trienco 14 years, 8 months ago
Quote:Original post by cache_hit
It serves no other purpose except to change the access specifier of base class members in the derived class.

Incorrect. using can move hidden declarations from a base class to the derived class.
struct Base {  void foo(int) {}  void foo(void) {}};struct Derived : Base {  void foo(int) {}  //using Base::foo;};int main(int, char **) {  Derived d;  d.foo();      return 0;}

Without the using this will fail to compile because Derived::foo(int) hides both Base::foo(int) and Base::foo(void). This has nothing to do with access specifiers, but is a scope modifier.
Advertisement
ok, fair enough. Didn't know about that. But in any case changing access is "the other" purpose of the using keyword then, since that's how you expose base class methods in private/protected inheritance.
Thanks, SiCrane, for the example that shows why the rule exists. And thanks for all the input folks. Although it still remains to be seen what the standard actually says, it appears that 'using' is affected by the access modifier. I find this disconcerting, but if this is what the standard says, I'll have to modify where I place the 'using' statements in my class.
FWIW I dug up my copy of the C++ Standard, and here's what we have.

7.3.3 The using declaration [namespace.udecl]
----1 A using-declaration introduces a name into the declarative region in which the using-declaration appears.
That name is a synonym for the name of some entity declared elsewhere.

----2 The member name specified in a using-declaration is declared in the declarative region in which the using-declaration
appears. [Note: only the specified name is so declared; specifying an enumeration name in a
using-declaration does not declare its enumerators in the using-declaration’s declarative region. ]

----3 Every using-declaration is a declaration and a member-declaration and so can be used in a class definition.

Example:
struct B {   void f(char);   void g(char);   enum E { e };   union { int x; };};struct D : B {   using B::f;   void f(int) { f(’c’); } // calls B::f(char)   void g(int) { g(’c’); } // recursively calls D::g(int)};


Skipping forward a little from here, we have:

----15 The alias created by the using-declaration has the usual accessibility for a member-declaration.

Example:

class A {private:   void f(char);   public:   void f(int);protected:   void g();};class B : public A {   using A::f; // error: A::f(char) is inaccessiblepublic:   using A::g; // B::g is a public synonym for A::g};


16 [Note: use of access-declarations (11.3) is deprecated; member using-declarations provide a better alternative.

Finally, referring to 11.3 to see what an "access declaration" is, it says:


11.3 Access declarations [class.access.dcl]

1---- The access of a member of a base class can be changed in the derived class by mentioning its qualified-id in the derived class declaration. Such mention is called an access declaration. The effect of an access declaration is defined to be equivalent to the declaration

using <qualified-id>;




So, it appears that protection level modification is a feature of the using keyword.
Quote:Original post by swiftcoderThat is as maybe, but g++ *does* allow me to promote protected functions from a base-class into public visibility - and that is an operation I am not entirely happy with.


Why? This is just a much more convenient way than
public:  void f() { Base::f(); }  void f(float x) { return Base::f(x); }  int g() { return Base::g(); }


Just lacking a bit of fine control if you only want to make a few overloaded versions available. Generally 'using' won't let you do anything that you couldn't do without it. So technically you shouldn't be comfortable with being allowed to declare a non-virtual function of the same name in a derived class either.

Also note that my "doesn't work" comment was in regard to _private_ members of your base class. They are and remain inaccessible in your derived class and ergo can't be made less than private (and thanks to cache-hit we now know it's not just VC, it's the standard).
f@dzhttp://festini.device-zero.de

This topic is closed to new replies.

Advertisement