Found this strange compilation behavior, checked on VS2012, VS2017 and https://www.onlinegdb.com/online_c++_compiler)
Basically for private nested classes you can call public functions outside, but not public constructors.
3 questions:
what is the reasoning behind compiler letting me call func()?
if compiler lets me call func(), why I cannot call ctor?
if I cannot call ctor, how come emplace_back is able to do it?
class Outer {
struct PrivateInner {
PrivateInner() {}
void func() {}
};
public:
PrivateInner inner;
std::vector<PrivateInner> innerVect;
};
void f1()
{
Outer c;
c.inner.func(); // COMPILING, but why?
}
void f2()
{
Outer c;
c.innerVect.push_back(Outer::PrivateInner()); // NOT COMPILING, why no access to ctor if there is access to func()?
c.innerVect.emplace_back(); // COMPILING, but why? Doesn't it call Outer::PrivateInner inside?
}
As I see I still can create a (static) function createObject():
class Outer {
struct PrivateInner {
PrivateInner() {}
static PrivateInner createObject() { return PrivateInner(); }
void func() {}
};
.....
};
and then call it.
createObject() may be non-static if calling static from instances is not pure standard thing.
c.innerVect.push_back(c.inner.createObject()); // COMPILING
to "hack" compilation
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private.
Accessing the Private Members Write an inner class in it, return the private members from a method within the inner class, say, getValue(), and finally from another class (from which you want to access the private members) call the getValue() method of the inner class.
A nested class is a class which is declared in another enclosing class. A nested class is a member and as such has the same access rights as any other member. The members of an enclosing class have no special access to members of a nested class; the usual access rules shall be obeyed.
A nested type has access to all of the members that are accessible to its containing type. It can access private and protected members of the containing type, including any inherited protected members.
Note that the nested struct
PrivateInner
is declared as private
, so only Outer::PrivateInner
is private
, you can't use this name to declare variable like Outer::PrivateInner pi;
without sufficient access right, but you can write it like decltype(Outer::inner) pi;
.
On the other hand, its constructor and member function are public
, so they can be called.
c.inner.func(); // COMPILING, but why?
func()
is public
, so if you have got an instance of type Outer::PrivateInner
you can call func
on it.
c.innerVect.push_back(Outer::PrivateInner()); // NOT COMPILING, why no access to ctor if there is access to func()?
It has nothing to do with the constructor, you just can't use the name Outer::PrivateInner
here.
c.innerVect.emplace_back(); // COMPILING, but why? Doesn't it call Outer::PrivateInner inside?
The constructor is public
, then it could be used to construct the object. std::vector
doesn't use the name like Outer::PrivateInner
directly; it uses the name specified as the template argument.
BTW: For the same reason,
c.innerVect.push_back(c.inner.createObject()); // COMPILING
but c.innerVect.push_back(Outer::PrivateInner::createObject());
won't compile.
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