In the bellow, the values of enum inside the class can be accessed by the name of the class.(I didn't even instantiate the class!)
class Shifting
{
public:
enum Value: char
{
UP, RIGHT, DOWN, LEFT
};
private:
Value value_;
};
std::cout << Shifting::RIGHT << std::endl; // 1
Does this mean that enum within a class is static?
If not, how to statically declare an enum?
This
enum Value: char
{
UP, RIGHT, DOWN, LEFT
};
this is a declaration of a type. It is not a data member of the enclosing class. The class has only this private data member.
Value value_;
of the enumeration data.
An enumerations declaration declares named enumerators. But they in turn are not data members of the enclosing class.
It is the same if you will declare a nested structure inside a class. For example
struct A
{
struct B
{
int x = 10;
};
B b;
};
Here is only one data member of the class A that is B b. The data member inside the structure declaration only provides the declaration of the structure B.
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.
I wanted to pass-in functions as arguments to a templated function without having any indirection. To achieve this I created two nested structs, each defining the function I wish to pass in to the templated function. Each of the structs accesses data members from the outside class B:
namespace A{
class B{
public:
B();
template <typename T>
void templatedFunction(T t){
//I pass one of the struct objects in to here, to invoke the desired function
t();
}
private:
struct X{
void operator(){
do();
}
void do(){
//Accesses the data members of class B
e->doSomething();
}
};
struct Y{
void operator(){
do();
}
void do(){
//Accesses the data members of class B
d.doSomething();
}
};
C* c;
D d;
E* e;
};
}
and the compiler errors I get are pretty much all of the format:
error: invalid use of non-static data member B::d
for the lines within the struct accessing the class data members and on the lines declaring the data members in B.
A nested class in C++ does not (automatically) have access to an instance of the containing class. It's just a class definition like any other. You need a B instance to access non-static data members of B.
You can restructure your nested class Y as
struct Y
{
void operator()( B& b ){
do( b );
}
void do( B& b ){
//Accesses the data members of class B
b.d.doSomething();
}
};
and fix your function template and calls, and class X, accordingly.
Note that your presented code for operator(), with no argument list, would not have compiled, but I'm not downvoting since you are stopped by another compilation error (i.e., possibly it is the real code you're showing).
If you have a struct (or class for that matter) nested in another class, it it not treated specially in any way. It works exactly the same as if the struct was defined outside of the enclosing class. The only thing which is different is the scope of nested class name. So, if you have
class A { class B{}; };
and
class B{}; class A {};
the only difference is that outside class A you need to name the class B as A::B in the first case, and just B in the second class. There is no other difference, and in particular class B does not gain any special access to class A members.
In my project, I have an enum defined in a class, that is used throughout that class. During refactoring, that enum was moved to another class. So I simply typedefed it in my original class, like this:
class A {
public:
enum E {e1, e2};
};
class B {
public:
typedef A::E E;
};
Now variable definitions, return values, function params, etc. work perfectly. Only when I want to access the values of the enum inside my second class, I still have to qualify them with the surroundig class's name,
e.g. E e = A::e1;
Is there a way to avoid this, or do I have to copy that into every occurance of the enum values?
You put each enumeration into a nested class that you can typedef within your own class:
class A {
public:
struct E { enum EnumType { e1, e2 } };
};
class B {
public:
typedef A::E E;
};
Then it's just E::EnumType instead of E but you get full auto-importation.
If you're not above using c++11, you could have a look at enum classes.
I have
class outer: public base
{
public:
class inner
{
foo();
}
}
How do i initialize these nested class?
Can I call foo() from the outer class?
Can you please tell me what is the thumb rule I should know while nesting class and accessing the members?
Thank you
I guess you're coming from java.
A c++ nested struct/class is like a java static nested type. It has no instance-relation with the containing type.
In fact you should be able to move the inner class to the containing namespace with no other changes than the potential need to mark the former inner class as a friend of the outer class.
See for demonstration http://ideone.com/ddjGX
How do i initialize these nested class?
You don't. You can only initialize members (class instances)
Can I call foo() from the outer class?
Not unless you are a friend or the method (foo()) is public
Can you please tell me what is the thumb rule I should know while nesting class and accessing the members?
I'd choose a nested type only if
the type is an implementation detail or depends on the outer class
the convenience of sharing static members (enums, typedefs, template arguments, static methods and fields) from the outer class: the inner class is implicitly a friend of the outer class.
I illustrated these 'rules of thumb' below. Note how the nested type has transparent access to private members of the outer class.
struct base {};
class outer: public base
{
private:
enum { some=42, special=67, implementation=999, details=-13 };
public:
struct inner
{
protected:
void foo() { int can_usethis = special + implementation + details; }
};
outer() : _inner() { }
void call_inner(inner& i) const
{
//i.foo(); // fails (protected)
}
void call_inner() const
{
//_inner.foo(); // fails (protected)
}
private:
inner _inner;
};
int main()
{
outer o;
outer::inner i;
// i.foo(); // fails: protected
o.call_inner(i);
}
You can instance inner object using scope operator :: (outer::inner()) . If you want to acceess foo() from outer class you maybe want to define outer like friend class of inner.
Sorry for naive question in C++. For below code, there is a class, inside which there is a union declaration having two variables. How to access the variables in the union using the class object in code below:
class my
{
public:
//class member functions, and oeprator overloaded functions
public:
union uif
{
unsigned int i;
float f;
};
private:
//some class specific variables.
};
if there is an object of type my defined like
my v1;
in a function later
Using v1 how do i access float f; inside union above in code?
also I want to watch the value of this float f in the watch window of a debugger(VS-2010), how to do that?
I tried v1.uif.f , this gave error in the watch window as : Error oeprator needs class struct or union.
v1.
You are only defining the union within the scope of the class, not actually creating a member variable of its type. So, change your code to:
class my
{
public:
//class member functions, and oeprator (sic) overloaded functions
public:
union uif
{
unsigned int i;
float f;
} value;
private:
//some class specific variables.
};
Now you can set the member variables in your union member, as follows:
my m;
m.value.i=57;
// ...
m.value.f=123.45f;
You never actually defined any member of that union. You only ever defined the union itself. There is no spoon float.
You've only defined the type of the uniion, you've not yet declared an object of this union type.
Try this:
class my
{
public:
union uif
{
unsigned int i;
float f;
};
uif obj; //declare an object of type uif
};
my v;
v.obj.f = 10.0; //access the union member
One option I don't see already here is that of an Anonymous Union, which is where you have no type or instantiation. Like so:
class my
{
public:
//class member functions, and oeprator (sic) overloaded functions
function(int new_i) { i = new_i;}
function(float new_f) { f = new_f;}
public:
union /* uif */
{
unsigned int i;
float f;
};
private:
//some class specific variables.
};
my m;
m.i=57;
m.f=123.45f;
Remember that with unions, it is only defined to read from the last member variable written to.
You have defined your union in your class, but you haven't created an instance of it! Try:
union uif
{
unsigned int i;
float f;
} myUif;
And then use v1.myUif.f (or i).