a in-class class access the outer class's data member - c++

I was trying to do this,
class Outer {
public:
struct inner_t {
void foo()
{
printf("%d", _x);
}
};
int _x;
};
int main()
{
Outer o;
o._x = 10;
}
The above can't compile with errors:
error: invalid use of non-static data member ‘Outer::_x’
But according to this post, inner_t can indeed access Outer::_x, what's wrong?

The problem is: inner_t does not know an instance of Outer to read _x from.
If you had written (for example):
void foo(const Outer *o)
{
printf("%d", o->_x);
}
Or if _x was a static member of Outer.
Then it should work (at least it will give no error).

You can indeed access _x of object of type Outer. You try basically to access instance field in static fashion. Pass an instance of Outer and then use it.

Related

nested class invalid use of non static data member

Hi i need help with this little example.
I am unable to use _test from the nested class
class random
{
public:
int _test;
class nestedClass
{
public:
void notify() override {
_test = 123;
}
} _nestedClass;
};
You can use/pass a pointer to the outer class named random to achieve what you want as follows:
void notify(random* p)
{
p->_test = 123;
}
This is because a nested class can access a non-static member of the enclosing class through a pointer to the enclosing class.
You can also pass arguments as:
void notify(random* p, int i)
{
p->_test = i;
}
You can't access the non-static member of random without a instance of random. You need to tell your nestedClass which _test it want to access. There may be many instances of random out there, and therefor, many _tests.
I think what you want is:
class random
{
public:
int _test;
class nestedClass
{
random& outer_;
public:
nestedClass(random& outer): outer_(outer) {
}
void notify() {
outer_._test = 123;
}
} _nestedClass;
random(): _nestedClass(*this) {
}
};

Visibility of private field of a template class from a template function

I have a template class
template<class T>
class MyClass
{
public:
MyClass() { privateField = 0; };
T getPrivateField() {
return privateField;
}
private:
T privateField;
};
and a template function which takes an instance of MyClass as a parameter
template<class T>
T foo(MyClass<T> mc) {
return mc.privateField;
}
I was confused by the fact that I can see a private field of MyClass in template function, but can't actually use it.
Here is an example of field visibility(screenshot)
Question:
Why can I see a private field of MyClass exactly in a template function and how can I disable it in my code(if it's possible)? Or it's just like a feature from Visual Studio?
private will limit your code's access to a member.
It does not make parts of your code invisible to tools that might make observations about what you have written. It's not private in the sense that a personal password might be private.
private does not mean that it is completely hidden from the outside, or that nobody outside of the class should be aware that it exists.
Consider this example:
#include <iostream>
struct foo {
int x = 0;
};
struct bar : foo {
private:
int x = 0;
};
int main() {
bar b;
b.x = 0;
}
Now suppose, main was written by a user who only knows about the public parts of the involved classes. They would have no way to understand why they get the error message:
<source>: In function 'int main()':
<source>:15:7: error: 'int bar::x' is private within this context
15 | b.x = 0;
| ^
<source>:10:13: note: declared private here
10 | int x = 0;
| ^
Admittetly this is a made up example, and bar can be considered broken. The point is just that your IDE would not necessarily do you a favor if it would not show any private members. Their presence or absence can change the meaning of code that is written only against the public interface.
Do not confuse visibility with access.
Consider how overload resolution behaves:
class X {
private:
void f(int value);
public:
void f(double value);
};
If we try to call X::f() with an int from outside:
int main() {
X obj;
obj.f(1234);
}
We still get the error:
<source>:10:15: error: 'void X::f(int)' is private within this context
obj.f(1234);
We definitely would not want main to call X::f(double) simply because it could not access the X::f(int) function. Otherwise, access could literally change the runtime meaning of your program.
C++ will
build an overload set from name lookup
perform resolution to pick the best match
verify access
In that order. That is, access is checked after the overload resolution has completed.

How can i modify variables in static member function?

I have a code below, i want to modify class's variables in static function but there is some error.
How can i fix it with "this" pointer?
There is no access to "this" pointer for static members in class,on the other hand I am trying to make an access to class variables in Static member function, therefore i am looking for a way to use "this" pointer of class "me" to do it.
class me {
public:
void X() { x = 1;}
void Y() { y = 2;}
static void Z() {
x = 5 ; y = 10;
}
public:
int x, y;
};
int main() {
me M;
M.X();
M.Y();
M.Z();
return 0;
}
I got this error :
invalid use of member ‘me::x’ in static member function.
You have two ways to do it :
Define your members as static if they are used in a static method.
Implement Dont use of static methods when class's members are non-static
Generally, the memory of static members or methods created once even when you dont create an object of your class. So you cannot use of a non-static members in a static method, because non-static members still have no memory While static methods have memory...
Try this :
public:
static void X() { x = 1;}
static void Y() { y = 2;}
public:
static int x;
static int y;
Dont forget to initialize static members :
int me::x = 0;
int me:y = 0;
You cannot use of this pointer inside a static method, because this may only be used inside a non-static member function. Notice the following :
this->x = 12; // Illegal use static `x` inside a static method
me::x = 12; // The correct way to use of `x` inside a static method
You can pass a pointer to an instance to the method:
class me {
public:
void X() { x = 1;}
void Y() { y = 2;}
static void Z(me* this_) { // fake "this" pointer
this_->x = 5 ;
this_->y = 10;
}
public:
int x, y;
};
int main() {
me M;
M.X();
M.Y();
M.Z(&M); // this works, but
// usually you call static methods like this
// me::Z(&M);
return 0;
}
You are trying to use a non-static member from a static member function. That's why it's giving you an error.
You can fix this by making the member function non-static (by removing static keyword). You could also make the variable static, so that your static member function can access it, but if you do so, the two other functions will still not compile.
Static method can access static members only.
class me {
public:
void X() { x = 1;}
void Y() { y = 2;}
static void Z() {
x = 5 ; y = 10;
}
public:
static int x, y;
};
int main() {
me M;
M.X();
M.Y();
M.Z();
return 0;
}
Adding to that #nivpeled said, think about this:
You may create several instances of me on your program. Which ones of the instances the static Z() method should modify?
I have the ultimate solution for you here lol.
I've asked this question so many time but instead of thinking or trying to solve the problem people starts judging my design which I think is funny.
So I have to explain that in some situations you will be in need to make static members gain access to non static ones, such case when you use a scripting interface in you program(Lua for example) that interface can only access static members of a class, which those members need to access to non static, anyways lets see how to do it.
class me {
public:
me() { This = this; } // Or you can assign it wherever you want
void X() { x = 1;}
void Y() { y = 2;}
static me* This; // Here is our "this" pointer :P
static void Z() {
This->x = 5 ; This->y = 10;
}
public:
int x, y;
};
//Remember to initialize it to avoid any linker's errors
me* me::This = nullpter; // or NULL or even 0
int main() {
me M;
// now you can access "this" pointer the usually way
M.X();
M.Y();
M.Z();
return 0;
}
After a while of thinking this is the most efficient solution i found.

Confusing Private variable access

Can private variable of one instance be available in the function of other instance.
The following code is printing 5
#include <iostream>
class A
{
public:
A(int value) {
x = value;
}
void printValue(A *obj) {
std::cout << obj->x;
}
private:
int x;
};
void main()
{
A obj1(3);
A obj2(5);
obj1.printValue(&obj2);
getchar();
return;
}
Can anyone please explain why this happens. Thank you.
Yes, it can. private: and protected: restrictions are per class, not per instance. What matters is where the code doing the access is located. If the code accessing something private is located in the same class, or in a friend class, or a friend function, then access is allowed.
Scope of being private applies to anything inside that type, not any only this instance.
From MSDN: "When preceding a list of class members, the private keyword specifies that those members are accessible only from member functions and friends of the class."
Let's modify printValue:
void printValue()
{
A *obj = this;
std::cout << obj->x;
}
If you say this shouldn't get compiled because by obj we are trying to access element of other object. If that holds true, no class can even be made to access element of its own. Copy/Move constructors, (move) assignment operators won't work.
Yes both Obj1 and Obj2 are of class A. So the member function certainly can access anything inside the object. To get more understanding, you should try to understand how a member function actually operates on an object through which it is called.
Let us take your example and adding one more function printValue() to it to explain more:
#include <iostream>
class A
{
public:
A(int value) {
x = value;
}
void printValue(A *obj) {
std::cout << obj->x;
}
void printValue() { // who supplies 'this' pointer accessible inside the function
std::cout<< this->x;
}
private:
int x;
};
void main()
{
A obj1(3);
A obj2(5);
obj1.printValue(&obj2);
getchar();
return;
}
note that I have added a member function void printValue(); and it uses this->x, which is provided by the compiler and the function call for
obj1.printValue(&obj2) is translated by compiler to printvalue(this, &obj2).
That is why when you call obj1.printValue() that i have added, it will be called like
printValue(this) where this = &obj1 provided by the compiler.
so effectively a member function always access an object using its pointer. In your case, there are 2 objects: 1 that you provide and one that is supplied by the compiler.
I hope this explains your doubt.
This behavior is not only logical, but also very useful. Consider
class Point2D {
public:
Point2D (int x, int y) : x(x), y(y);
Point2D& operator+=(const Point2D& other) {
x += other.x;
y += other.y;
return *this;
}
private:
int x, y;
}
If you could not access other's private members in operator+=, you'd be forced to make public getters and setters and the whole point of having x and y private would be arguably lost. Hence private hides the members form the outside world, but not from instances of the same class.

Can inner classes access private variables?

class Outer {
class Inner {
public:
Inner() {}
void func() ;
};
private:
static const char* const MYCONST;
int var;
};
void Outer::Inner::func() {
var = 1;
}
const char* const Outer::MYCONST = "myconst";
This errors out when I compile with class Outer::Inner' has no member named `var'
An inner class is a friend of the class it is defined within.
So, yes; an object of type Outer::Inner can access the member variable var of an object of type Outer.
Unlike Java though, there is no correlation between an object of type Outer::Inner and an object of the parent class. You have to make the parent child relationship manually.
#include <string>
#include <iostream>
class Outer
{
class Inner
{
public:
Inner(Outer& x): parent(x) {}
void func()
{
std::string a = "myconst1";
std::cout << parent.var << std::endl;
if (a == MYCONST)
{ std::cout << "string same" << std::endl;
}
else
{ std::cout << "string not same" << std::endl;
}
}
private:
Outer& parent;
};
public:
Outer()
:i(*this)
,var(4)
{}
Outer(Outer& other)
:i(other)
,var(22)
{}
void func()
{
i.func();
}
private:
static const char* const MYCONST;
Inner i;
int var;
};
const char* const Outer::MYCONST = "myconst";
int main()
{
Outer o1;
Outer o2(o1);
o1.func();
o2.func();
}
An inner class has access to all members of the outer class, but it does not have an implicit reference to a parent class instance (unlike some weirdness with Java). So if you pass a reference to the outer class to the inner class, it can reference anything in the outer class instance.
Anything that is part of Outer should have access to all of Outer's members, public or private.
Edit: your compiler is correct, var is not a member of Inner. But if you have a reference or pointer to an instance of Outer, it could access that.
First of all, you are trying to access non-static member var outside the class which is not allowed in C++.
Mark's answer is correct.
Anything that is part of Outer should have access to all of Outer's members, public or private.
So you can do two things, either declare var as static or use a reference of an instance of the outer class to access 'var' (because a friend class or function also needs reference to access private data).
Static var
Change var to static If you don't want var to be associated with the instances of the class.
#include <iostream>
class Outer {
private:
static const char* const MYCONST;
static int var;
public:
class Inner {
public:
Inner() {
Outer::var = 1;
}
void func() ;
};
};
int Outer::var = 0;
void Outer::Inner::func() {
std::cout << "var: "<< Outer::var;
}
int main() {
Outer outer;
Outer::Inner inner;
inner.func();
}
Output- var: 1
Non-static var
An object's reference is a must to access any non-static member variables.
#include <iostream>
class Outer {
private:
static const char* const MYCONST;
int var;
public:
class Inner {
public:
Inner(Outer &outer) {
outer.var = 1;
}
void func(const Outer &outer) ;
};
};
void Outer::Inner::func(const Outer &outer) {
std::cout << "var: "<< outer.var;
}
int main() {
Outer outer;
Outer::Inner inner(outer);
inner.func(outer);
}
Output- var: 1
Edit - External links are links to my Blog.
var is not a member of inner class.
To access var, a pointer or reference to an outer class instance should be used. e.g. pOuter->var will work if the inner class is a friend of outer, or, var is public, if one follows C++ standard strictly.
Some compilers treat inner classes as the friend of the outer, but some may not. See this document for IBM compiler:
"A nested class is declared within the scope of another class. The name of a nested class is local to its enclosing class. Unless you use explicit pointers, references, or object names, declarations in a nested class can only use visible constructs, including type names, static members, and enumerators from the enclosing class and global variables.
Member functions of a nested class follow regular access rules and have no special access privileges to members of their enclosing classes. Member functions of the enclosing class have no special access to members of a nested class."