C++ access modifiers and 'using' declarations

Started by
23 comments, last by Trienco 14 years, 8 months ago
On topic again: my friend Google tells me ...

So you are indeed right that the additional scope should be necessary to let the compiler know that what you are calling is also depending on type T. But it is also correct that VS does not enforce this.

Edit (once again)
The link given above provides a technical explanation why you have to provide the scope. Now I think I remember I also stumbled across this problem when porting some Windows templates to Linux. But we humans forget so fast ... [grin]
------------------------------------I always enjoy being rated up by you ...
Advertisement
Quote:Original post by WaterwalkerBut then, what would prevent me from inheriting another class from this guy and declare same nasty public using's for the whole interface?


Without guarantee that the standard says the same, but with VC the result is as expected. You simply can't access an inherited private member, so you can't "unprivate" it with 'using'. That would have been somewhat sabotaging the whole point of making it private (almost like casting away a 'const').
f@dzhttp://festini.device-zero.de
Quote:Original post by magic_man
I understand the idea behind the using statement yet not in the protected interface.


I place my data members in a final block in the C++ class interface (to avoid cluttering the first block which contains the services available to a class user), so the access modifier is typically private or protected. I put my 'using' statements in the last block just to put them *somewhere*, thinking that the access modifier has nothing to do with 'using'. I was not intentionally trying to modify the access rights for anything.

This is the point of original post. In my opinion, 'using' has to do with scoping identifiers. public/protected/private has to do with access rights. The fact that the two concepts can (apparently) interact is not intuitive.
Quote:Original post by Dave Eberly
In my original post, I mentioned that someone had explained the rationale to me, but I have forgotten it. I find it completely uninituitive that a compiler would check for mMember in a global scope when it is a base-class member. No doubt there is some "edge case" that led to this rule; I just cannot recall it.

IIRC, it goes something like:
void foo(void) {  std::cout << "::foo()\n";};template <class T>struct Bar : T {  Bar() {    foo(); // intends to call ::foo()  }};struct Baz {  void foo(void) {    std::cout << "Baz::foo()\n";  }};Bar<Baz> f;

With the gcc template implementation creating f results in "::foo()" getting printed. With MSVC you get "Baz::foo()". The standards committee decided that the global version of foo() should the one being called because that's the only one around when the template was defined. Introducing an additional foo() with the base class probably changes the meaning unintentionally. Also, if you follow the gcc method of doing things it's relatively easy to force the compiler to choose Baz::foo() if you really want it. It's harder to work the other direction.
Quote:Original post by Dave Eberly
@Waterwalker. You edited your post, but swiftcoder answered correctly.

This is unfair, he quoted my unqualified statements while I was already editing them away while he edited his own post [grin]

But like I said, Visual Studio does not enforce this rule so I had to google first to back up my uprising fears that yet again MS is not ANSI in this case. Next time I shall check first and post later.

------------------------------------I always enjoy being rated up by you ...
Quote:Original post by Dave Eberly
I have an unexpected compiler error in the following code. It appears as if
the access modifier before a 'using' declaration changes the access rights
of a base-class function from 'public' to 'protected'.

*** Source Snippet Removed ***

Is this behavior dictated by the ANSI C++ rules? I would find it annoying
that in addition to specifying 'using' statements in a derived template
class in order to use base-class members without having to scope with
'this->mBaseClassMember', I would also have to place the 'using' statements
in blocks with the proper access modifier.

Speaking of that annoyance, someone once explained to me why 'using' is now
needed in this context, but I do not recall the explanation. Anyone care to
enlighten me about this? Thanks.


Maybe I'm misunderstanding the problem description, but I thought this was the entire point of the using keyword at class scope. For example, suppose you use inherit privately from some class. Now all of the base class's members appear to be private to clients of the derived class, regardless of their previous scope. So in effect they're private to the derived class. You then put a using statement at class scope under a public protection level and all the members then become public.

Am I missing something?

Secondly, regarding your other point about needing to use the this keyword to dereference the item if it DOESN'T have a using statement, that makes no sense. You're inheriting publicly and calling a base class function from a derived function. This is perfectly fine, so I'm not sure I understand why you would need to put a using in order to make it so that you did not have to write this->.

I don't have a copy of G++ but I tried it on Visual C++ 2008 and it works fine as you said. As in it compiles the code if I delete the 'using' line. But NOT working seems completely unbelievable to me, it's just basic inheritance and calling a base class function.

Maybe I'm just not aware of this rule since I use Visual C++ exclusively, but I would be very much interested if someone could point out in the Standard where it explains this because it is pretty surprising to me.
Quote:Original post by Trienco
Quote:Original post by WaterwalkerBut then, what would prevent me from inheriting another class from this guy and declare same nasty public using's for the whole interface?
Without guarantee that the standard says the same, but with VC the result is as expected. You simply can't access an inherited private member, so you can't "unprivate" it with 'using'. That would have been somewhat sabotaging the whole point of making it private (almost like casting away a 'const').
That 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.

The question, then, is what the standard says. Is GCC implementing the correct behaviour throughout, or should it only be possible to tighten the access controls (a la protected inheritance), rather than loosen them as well?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:Original post by Dave Eberly

This is the point of original post. In my opinion, 'using' has to do with scoping identifiers. public/protected/private has to do with access rights. The fact that the two concepts can (apparently) interact is not intuitive.

I am afraid you are incorrect. The using statement brings the function into the derived class and overrides the base class member function. The derived function access rights are as as if it was declare at the using statement and therefore is protected. Yet in the user class you try and call a function which you think is in the base, yet it is hidden and is in the derived instance in the protected interface.
"You insulted me!" I did not say that in the private message Tom Sloper!
Quote:Original post by swiftcoder
Quote:Original post by Trienco
Quote:Original post by WaterwalkerBut then, what would prevent me from inheriting another class from this guy and declare same nasty public using's for the whole interface?
Without guarantee that the standard says the same, but with VC the result is as expected. You simply can't access an inherited private member, so you can't "unprivate" it with 'using'. That would have been somewhat sabotaging the whole point of making it private (almost like casting away a 'const').
That 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.

VS2008 does allow this as well. But I have to agree that I am not happy with that the same way I am not happy that it is actually possible to change access rights by deriving classes with either function overloading or using statements.

But we should not hijack this thread for discussing the general downsides of changing access rights. [smile]
------------------------------------I always enjoy being rated up by you ...
Quote:Original post by Waterwalker
But I have to agree that I am not happy with that the same way I am not happy that it is actually possible to change access rights by deriving classes with either function overloading or using statements.



Again, this is the entire *point* of the using statement at class scope. It serves no other purpose except to change the access specifier of base class members in the derived class.

This topic is closed to new replies.

Advertisement