2

I've been looking high and low for an answer to what I thought was a fairly simple question: Why are access declarations deprecated?

class A
{
public:
    int testInt;
}

class B: public A
{
private:
   A::testInt;
}

I understand that it can be fixed by simply plopping "using" in front of A::testInt, but without some sort of understanding as to why I must do so, that feels like a cheap fix.

Worse yet, it muddies my understanding of using declarations/directives, and the scope resolution operator. If I must use a using declaration here, why am I able to use the SRO and only the SRO elsewhere? A trivial example is std::cout. Why not use using std::cout? I used to think that using and the SRO were more or less interchangeable (give or take some handy functionality provided with the "using" keyword, of which I am aware, at least in the case of namespaces).

I've seen the following in the standard:

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 qualified-id; is defined to be equivalent >to the declaration using qualified-id; [Footnote: Access declarations are deprecated; member >using-declarations (7.3.3) provide a better means of doing the same things. In earlier >versions of the C++ language, access declarations were more limited; they were generalized >and made equivalent to using-declarations - end footnote]

However, that really does nothing other than confirm what I already know. If you really boiled it down, I am sure my problem stems from the fact that I think using and the SRO are interchangeable, but I haven't seen anything that would suggest otherwise.

Thanks in advance!

Brandon
  • 23
  • 1
  • 6
  • 1
    _`deprecated`_ in which exact standard version? [tag:c++11]? This might be very relevant for your question ... – πάντα ῥεῖ Mar 16 '14 at 18:54
  • This is where my nubbishness will show. To answer your question: I'm not sure. I've seen that blockquote posted everywhere, so I just assumed it was universally true and would subsequently apply to me. http://stackoverflow.com/questions/2084801/c-using-declaration-scope-and-access-control - An example, if it helps. I've been working my way through Alex Allain's "Jumping into C++" and using learncpp.com. Outside of that, I don't know much. I hope that doesn't leave my question shrouded in too much ambiguity. – Brandon Mar 16 '14 at 19:05
  • 2
    I've been using c++ for a long time, and I didn't even know you could change the access level of a base class member from a derived class. – johnb003 Mar 16 '14 at 19:05
  • 1
    @πάνταῥεῖ: in a funny twist on things, access declarations were deprecated already in C++98, the first C++ standard. – Cheers and hth. - Alf Mar 16 '14 at 19:06
  • They were in pre-standard C++ and were kept for compatibility with code written in the 1980s and early 1990s, but should never ever ever be used now. – Jonathan Wakely Mar 16 '14 at 19:09
  • Also, access declarations have been removed for C++14, so they should _really_ never ever ever be used now. – Jonathan Wakely Mar 16 '14 at 19:21
  • @Jefffrey, your edit removed the fixes I made to the markup, please restore them – Jonathan Wakely Mar 16 '14 at 19:23
  • @Brandon OT: _' I give you permission to flame me for my lack of SO knowledge.'_ No need to worry, well survived ;) ... – πάντα ῥεῖ Mar 16 '14 at 19:26
  • 1
    @JonathanWakely, except that you shouldn't fix the code, ever. – Shoe Mar 16 '14 at 19:28

1 Answers1

5

If I must use a using declaration here, why am I able to use the SRO and only the SRO elsewhere?

Huh? You are not able to. Not to re-declare a name in a different scope (which is what an access declaration does).

A trivial example is std::cout. Why not use using std::cout?

Because they're not the same thing, not even close.

One refers to a name, the other re-declares a name.

I am sure my problem stems from the fact that I think using and the SRO are interchangeable

I agree that's your problem, because you are entirely wrong. Following a using declaration it is not necessary to qualify the name, but that doesn't make them interchangeable.

std::cout is an expression, it refers to the variable so you can write to it, pass it as a function argument, take its address etc.

using std::cout; is a declaration. It makes the name cout available in the current scope, as an alias for the name std::cout.

std::cout << "This is an expression involving std::cout\n";
using std::cout;  // re-declaration of `cout` in current scope

If you're suggesting that for consistency you should do this to write to cout:

using std::cout << "This is madness.\n";

then, erm, that's madness.

In a class, when you want to re-declare a member with a different access you are re-declaring it, so you want a declaration. You aren't trying to refer to the object to write to involve it in some expression, which (if it was allowed at class scope) would look like this:

class B: public A
{
private:
   A::testInt + 1;
};

For consistency with the rest of the language, re-declaring a name from a base class is done with a using-declaration, because that's a declaration, it's not done with something that looks like an expression.

class B: public A
{
private:
   A::testInt; // looks like an expression involving A::testInt, but isn't
   using A::testInt;  // re-declaration of `testInt` in current scope
};

Compare this to the std::cout example above and you'll see that requiring using is entirely consistent, and removing access declarations from C++ makes the language more consistent.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521