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
}
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
.
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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With