Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access to private nested class returned from member function

Tags:

c++

Please help me understand why it is possible for a class member function to return a private nested class object, and why it is then possible to call member functions on that private nested class, eg:

class Y
{
    class X
    {
    public:
        void f() { cout << "Hello World" << endl; }
    };

public:
    X g() { return X(); }
};

void h()
{
    Y::X x;     // Error, as expected: class Y::X is private.
    x.f();      // Error.

    Y y;        // OK.
    y.g().f();  // OK. But why???
}

I tested with GCC and Visual C++, and that last line compile on both. I cannot seem to find anything in the C++ standard that would make this valid. Any ideas why this works?

Edit:

Another observation:

void i()
{
    Y y;

    Y::X x2 = y.g(); // Error: class Y::X is private
    x2.f();          // Error

    auto x3 = y.g(); // OK
    x3.f();          // OK
}
like image 431
Barnett Avatar asked Oct 18 '15 11:10

Barnett


3 Answers

Making a nested class private doesn't mean external scopes can never use an instance of that class. Access specifiers affect names, and your main function never attempts to name Y::X.1 The only place where Y::X is named is within Y, which of course has access to its own private members. That the function returns an instance of Y::X to main isn't particularly relevant.

[C++14: 11/1]: A member of a class can be

  • private; that is, its name can be used only by members and friends of the class in which it is declared.
  • protected; that is, its name can be used only by members and friends of the class in which it is declared, by classes derived from that class, and by their friends (see 11.4).
  • public; that is, its name can be used anywhere without access restriction.

Admittedly, the standard does not have any text to explicitly unconfuse you and point out that access to the entities themselves is not controlled by these keywords, but that is definitely the intent and, ultimately, as far as the legalese goes.

1 It does name Y::X::f, but that name is public.

like image 59
Lightness Races in Orbit Avatar answered Nov 13 '22 22:11

Lightness Races in Orbit


why it is possible for a class member function to return a private nested class object

A nested class is a class member too, and the member function has the access right on the private member.

and why it is then possible to call member functions on that private nested class

You're not using the private nested class name here, i.e. Y::X. And Y::X::f() is a public function, so it's possible to call it directly.

like image 29
songyuanyao Avatar answered Nov 13 '22 20:11

songyuanyao


Here you can find the example that you are looking for. f1 is public, f2 is private and triggers the error you are expecting:

#include <iostream>

class Y
{
    class X
    {
        public:
            void f1() { std::cout << "Hello World" << std::endl; }
        private:
            void f2() { std::cout << "Hello World" << std::endl; }
    };

    public:
        X g() { return X(); }
};

int main()
{
    // Y::X x;     // Error, as expected: class Y::X is private.
    // x.f();      // Error.

    Y y;         // OK.
    y.g().f1();  // OK. Because f1 is public.
    y.g().f2();  // Error. Because f2 is private.

    return 0;
}
like image 44
Chiel Avatar answered Nov 13 '22 22:11

Chiel