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
// ...}
Related
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.
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.
I'm reading Scott Meyers' C++ and come across this example:
class GamePlayer{
private:
static const int NumTurns = 5;
int scores[NumTurns];
// ...
};
What you see above is a declaration for NumTurns, not a definition.
Why not a definition? It looks like we initialize the static data member with 5.
I just don't understand what it means to declare but not define a variable with the value 5. We can take the address of the variable fine.
class A
{
public:
void foo(){ const int * p = &a; }
private:
static const int a = 1;
};
int main ()
{
A a;
a.foo();
}
DEMO
Because it isn't a definition. Static data members must be defined outside the class definition.
[class.static.data] / 2
The declaration of a static data member in its class definition is not
a definition and may be of an incomplete type other than cv-qualified
void. The definition for a static data member shall appear in a
namespace scope enclosing the member’s class definition.
As for taking the address of your static member without actually defining it, it will compile, but it shouldn't link.
you need to put a definition of NumTurns in source file, like
const int GamePlayer::NumTurns;
Can some one please explain the scope of int A and int B in the void func() and in void func1()?
class C {
struct S {
int A;
};
int B
public :
void func(){
}
void func1(){
}
};
Not sure I fully understand what you're asking for, but if I do, I'll try to answer.
Functions func() and func1() are member functions of C, so they have identical access to the exact same names here. Variable B, being a member variable of C, can be referred directly withing func() and func1() without qualifying it with any namespace.
Variable A on the other hand, being a public, non-static member variable of S, requires first instantiating an object of type S before being accessed, like this:
void func()
{
S s;
B = 0; // Directly accessible, member variable of `C`
s.A = B; // A is a non-static member variable of `S`, requires an object
A == 3; // ERROR! A is not a member variable of C
}
We're not allowed to define a functor struct inside a function because one is not allowed to use function declared structs in the instantiation of function templates.
Are there any other significant pitfalls to be aware of? E.g. would this be bad:
int foo()
{
struct Scratch
{
int a, b, c;
};
std::vector<Scratch> workingBuffer;
//Blah Blah
}
1. C++ standard forbids using locally-defined classes with templates.
14.3.1/2: A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.
A code example:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as
// template-argument
X<S*> x4; // error: pointer to local type
// used as template-argument
}
Here is a little more reference from IBM documentation:
2. Declarations in a local class can only use type names, enumerations, static variables from the enclosing scope, as well as external variables and functions.
A Code Example:
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
return 0;
}
3. A local class cannot have static data members
A Code Example:
void f()
{
class local
{
int f(); // error, local class has noninline
// member function
int g() {return 0;} // valid, inline member function
static int a; // error, static is not allowed for
// local class
int b; // valid, nonstatic variable
};
}
The scope of the local classes is the function in which they're defined.But that isn't interesting in itself1.
What makes local classes interesting is that if they implement some interface, then you can create instances of it (using new) and return them, thereby making the implementation accessible through the base class pointer even outside the function.
Some other facts about local classes:
They cannot define static member variables.
They cannot access nonstatic "automatic" local variables of the enclosing function. But they can access the static variables.
They can be used in template functions. They cannot be used as template argument, however.
If they defined inside template function, then they can use the template parameters of the enclosing function.
Local classes are final, that means users outside the function cannot derive from local class to function. Without local classes, you'd have to add an unnamed namespace in separate translation unit.
Local classes are used to create trampoline functions usually known as thunks.
Some references from the Standard (2003)
9.8 Local class declarations [class.local]
\1. 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.
Local structs / classes can't have static data members, only static member functions. Also, they can't be templates.
Yes. Local classes can't be used as template parameters in C++03
local structs are perfectly legal, even in C++98. You cannot use them with templates in C++98 though, whereas you can in C++0x. g++ 4.5 supports using local structs with templates in -std=c++0x mode.