I have code like this:
class outer{
int x;
class inner{
int y;
}
void print(int t_x){
std::cout << t_x;
}
}
Is there a way to create only instance of class inner? And if this is possible, will this object have acces to outer::print function ?
Is there a way to create only instance of class inner?
Yes, you can let have outer creating as many instance independent instances (e.g. as static members or local variables in static member functions) of inner as you want.
And if this is possible, will this object have acces to outer::print function ?
No. outer::print() is only available with an instance of outer, so at least a parameter or a local instance of outer will be needed.
The outer and inner class declarations are completely independent regarding instantiation. It's only about the scope:
The inner type is only seen at the private outer class scope (can be circumvented using anonymous auto types outside of outer received through functions)
inner has access to any public, protected and private members of outer (special scope priviledges)
outer has access to any public members of inner as usual (no special priviledges)
That's called a nested class, not an inner class.
The most frequent use case of nested classes are iterators of standard library. Their templates are declared in related container templates.
To create an instance of nested class, one should have access to its declaration. It can be instantiated only from outer class or from a friend of that class.
class outer{
int x;
class inner;
public:
void doThings();
};
class outer::inner
{
public:
void print(class outer *p)
{
std::cout << "x=" << p->x;
}
};
void outer::doThings()
{
outer::inner a;
a. print(this);
}
int main()
{
outer a;
a.doThings();
return 0;
}
Methods of outer::inner will have access to private and protected members of outer
9.7 Nested class declarations [class.nest]
1 A class can be declared within another class. A class declared
within another is called a nested class. The name of a nested class is
local to its enclosing class. The nested class is in the scope of its
enclosing class. [ Note: See 5.1 for restrictions on the use of
non-static data members and non-static member functions. —end note ]
int x;
int y;
struct enclose {
int x;
static int s;
struct inner {
void f(int i) {
int a = sizeof(x); // OK: operand of sizeof is an unevaluated operand
x = i; // error: assign to enclose::x
s = i; // OK: assign to enclose::s
::x = i; // OK: assign to global x
y = i; // OK: assign to global y
}
void g(enclose* p, int i) {
p->x = i; // OK: assign to enclose::x
}
};
};
inner* p = 0; // error: inner not in scope
2 Member functions and static data members of a nested class can be
defined in a namespace scope enclosing the definition of their class.
struct enclose {
struct inner {
static int x;
void f(int i);
};
};
int enclose::inner::x = 1;
void enclose::inner::f(int i) { / ... / }
3 If class X is defined in a namespace scope, a nested class Y may be declared in class X and later defined in the definition of class X
or be later defined in a namespace scope enclosing the definition of
class X.
class E {
class I1; // forward declaration of nested class
class I2;
class I1 { }; // definition of nested class
};
class E::I2 { }; // definition of nested class
4 Like a member function, a friend function (11.3) defined within a
nested class is in the lexical scope of that class; it obeys the same
rules for name binding as a static member function of that class
(9.4), but it has no special access rights to members of an enclosing
class.
Related
Title says it all. Suppose I have this:
struct Outer
{
struct Inner
{
void a(int i) {
Outer::a(i); // Error: Illegal of non-static member function
}
};
void a(int i) {}
};
How would that Inner::a declaration be?
There is no way. There isn't even a fixed relation between outer and inner class (like aggregation), you could create inner instances without outer instances and vice versa.
BTW: The fact that the two memberfunctions are both called a is totally irrelevant here.
How to call outer classes functions with the same name as the calling inner class function?
You must need to create an instance of the class before trying to access the member functions directly.
Thus, there are two ways to do this:
Declare the function signature with static.
Create an instance of the Outer and access the member function with a dot operator.
Example 1:
struct Outer {
struct Inner {
void a(int i) {
Outer::a(i); // direct member function access
}
};
static void a(int i) { // declared as static
std::cout << i << std::endl;
}
};
int main(void) {
Outer::Inner in;
in.a(10); // Inner class calls the member of Outer class's a(int)
return 0;
}
Example 2:
struct Outer {
struct Inner {
void a(int i) {
Outer x; // instance to the class Outer
x.a(i); // accessing the member function
}
};
void a(int i) { // outer class definition
std::cout << i << std::endl;
}
};
int main(void) {
Outer::Inner in; // creating an instance of Inner class
in.a(10); // accessing the Inner member function (which accesses
// Outer class member function)
return 0;
}
If you came from java, the declaration in C++
class Outer {
class Inner {
};
};
means in java:
class A {
static class B { // <- static class
};
};
all inner classes in c++ are kinda "equivalent" to static inner classes in java
Is it possible to use a variable in an inner class declared in Outer class .
I would like to achieve like the following. Is it possible.
I am getting the following error.
prog.cc: In constructor 'Outer::Inner::Inner()': prog.cc:12:25: error: invalid use of non-static data member 'Outer::i'
Inner( ) { i = 5; };
#include <iostream>
using namespace std;
class Outer {
public:
int i;
class Inner; // forward declaration of Outer::Inner
friend class Inner;
class Inner {
Inner() {
i = 5;
};
};
};
int main() {
return 0;
}
Unlike Java, C++ "inner classes" have no connection to the outer class that created them. You will have to pass in a pointer or reference to the outer class.
From the working draft of the standard available online:
9.7 Nested class declarations [class.nest]
A class can be declared within another class. A class declared within another is called a nested class. The name of a nested class is local to its enclosing class. The nested class is in the scope of its enclosing class.
Example:
int x;
int y;
struct enclose {
int x;
static int s;
struct inner {
void f(int i) {
int a = sizeof(x); // OK: operand of sizeof is an unevaluated operand
x = i; // error: assign to enclose::x
s = i; // OK: assign to enclose::s
::x = i; // OK: assign to global x
y = i; // OK: assign to global y
}
void g(enclose* p, int i) {
p->x = i; // OK: assign to enclose::x
}
};
};
inner* p = 0; // error: inner not in scope
As you can see from the example provided in the document, the only way for a nested class to access a non-static member of the enclosing class is through a pointer to the enclosing class.
That is what happens in void g(enclose* p, int i)
In the c++ draft standard we have this statement in [class.nest]:
2 Member functions and static data members of a nested class can be defined in a namespace scope enclosing the definition of their class. [Example:
struct enclose {
struct inner {
static int x;
void f(int i);
};
};
int enclose::inner::x = 1;
void enclose::inner::f(int i) { /* ... */ }
—end example ]
My confusion is that if this is possible then why isn't the following possible:
struct enclose {
struct inner {
void f(int i);
};
void inner::f(int i) {}
};
error: cannot define member function 'enclose::inner::f' within 'enclose'
void inner::f(int i) {}
Doesn't the definition of f lie in the same scope enclosing the definition of the inner class?
If not, then why is this not allowed? What issue is there with defining this function in the class scope?
The wording you cited says it can be defined in namespace scope. You're attempting to define it within struct enclose, which is class scope, not namespace scope.
Hello I am wondering why C++ standard allows us in nested classes to access outer class's private fields, while it forbids to access inner class's private fields from the outer class. I understand, that this example:
class OuterClass{
public:
class InnerClass{
public:
void printOuterClass(OuterClass& outer) {cout << outer.m_dataToDisplay;};
};
private:
int m_dataToDisplay;
};
is fine, because thing, that Inner class sometimes can be complicated. But I think following scenario is also fine:
class Algorithm{
public:
class AlgorithmResults{
public:
void readAlgorithmResult();
private:
void writeAlgorithmResult();
};
void calculate(AlgorithmResults& results, Arguments...){
//calculate stuff
results.writeAlgorithmResult(results);
}
};
For me this structure makes perfect sense, although it is not allowed in C++. I also noticed, that for some time both were allowed in Java, but now second example is also forbidden.
What is the reason, that first example is allowed and another is denied?
Essentially, within a scope names declared earlier in that scope are valid and can be used directly (unless they're shadowed). Code outside a scope can't directly use names declared inside the scope. E.g. code after a curly braces block, can't directly use variables declared inside that block (an example of indirect use is when the outside code has access to a pointer to a static variable inside the curly braces block).
For the second example, just make Algorithm a friend of AlgorithmResults:
class AlgorithmResults
{
friend class Algorithm;
The nested classes could access outer class's private fields, because it's a member of the outer class, just same as the other members.
[class.access.nest]/1
A nested class is a member and as such has the same access rights as any other member.
On the other hand, the outer class doesn't have special access rights on the nested class, they're just normal relationship.
The members of an enclosing class have no special access to members of a nested class; the usual access rules ([class.access]) shall be obeyed. [ Example:
class E {
int x;
class B { };
class I {
B b; // OK: E::I can access E::B
int y;
void f(E* p, int i) {
p->x = i; // OK: E::I can access E::x
}
};
int g(I* p) {
return p->y; // error: I::y is private
}
};
— end example ]
Counter question: Why would you want to allow it?
If you need an outer class have access to an inner class' private internals, you can befriend:
class Foo {
public:
class Frob {
friend class Foo;
int privateDataMember;
};
Foo () {
Frob frob;
frob.privateDataMember = 3735928559;
}
};
C++ has no device to unfriend, so allowing default private access to an outer class would steal you a class design tool and yield reduced default encapsulation.
Can a class written in a method of another class(inner class), access the methods variables? I mean in the code below:
class A
{
void methodA( int a )
{
class B
{
void processA()
{
a++;
}
};
std::cout<<"Does this program compile?";
std::cout<<"Does the value of the variable 'a' increments?";
};
};
Is this legal?Does, the value of 'a' increments? Please suggest how.
Thanks,
Pavan.
No it is not legal
class B is a Local class to methodA().
class B cannot access nonstatic "automatic" local variables of the enclosing function. But it can access the static variables from the enclosing scope.
There are several restrictions on what local classes can have access to.
Here is an reference from the C++ Standard:
9.8 Local class declarations [class.local]
A class can be defined within a function definition; such a class is called a local class. The name of a local class is local to its enclosing scope. The local class is in the scope of the enclosing scope, and has the same access to names outside the function as does the enclosing function. Declarations in a local class can use only type names, static variables, extern variables and functions, and enumerators from the enclosing scope.
[Example:
int x;
void f()
{
static int s ;
int x;
extern int g();
struct local {
int g() { return x; } // error: x is auto
int h() { return s; } // OK
int k() { return ::x; } // OK
int l() { return g(); } // OK
};
// ...
}
local* p = 0; // error: local not in scope
—end example]
2. An enclosing function has no special access to members of the local class; it obeys the usual access rules (clause 11). Member functions of a local class shall be defined within their class definition, if they are defined at all.
3. If class X is a local class a nested class Y may be declared in class X and later defined in the definition of class X or be later defined in the same scope as the definition of class X. A class nested within a local class is a local class.
4. A local class shall not have static data members.
Short answer, no. Local classes in C++ do not have access to their enclosing function variables (with a few caveats). You can read more about C++ local classes here, and also see this nice SO answer. For emphasis:
A local class is declared within a function definition. Declarations in a local class can only use type names, enumerations, static variables from the enclosing scope, as well as external variables and functions.
int x; // global variable
void f() // function definition
{
static int y; // static variable y can be used by
// local class
int x; // auto variable x cannot be used by
// local class
extern int g(); // extern function g can be used by
// local class
class local // local class
{
int g() { return x; } // error, local variable x
// cannot be used by g
int h() { return y; } // valid,static variable y
int k() { return ::x; } // valid, global x
int l() { return g(); } // valid, extern function g
};
}
int main()
{
local* z; // error: the class local is not visible
// ...}