How does a function access private data member of a class object? - c++

My code:-
#include<iostream>
using namespace std;
class a{
private:
int x;
public:
a(int data)
{
x=data;
}
friend void printPrivateMember(a);
};
void printPrivateMember(a obj)
{
cout<<obj.x; //I can access private data member by an object inside this function.
}
int main()
{
a obj1(5);
printPrivateMember(obj1);
cout<<obj1.x; //this gives error
return 0;
}
I wanted to know as to how can I access a PRIVATE data type by an object in the friend function but cannot do so in main.
When I read about access specifier . It was specified that private can be accessed by only member functions (I don't have a problem with the friend function) and not by the object of that class. I wanted to know as to what difference is there because of which I can access private member by an object in one case and cannot do so in another. The same is applicable for copy constructor.

That's exactly what friend functions do: any friend function of a class can access it's private members. Since your printPrivateMember is declared as a friend of a, it can access it's private x member. Since main is not a friend function, it can't.
Forestalling a question about declaring main as friend, this question covers it.

Because friends could do that.
$11/1 Member access control [class.access]
(emphasis mine)
1 A member of a class can be
(1.1) — private; that is, its name can be
used only by members and friends of the class in which it is
declared.
(1.2) — protected; that is, its name can be used only by
members and friends of the class in which it is declared, by classes
derived from that class, and by their friends (see 11.4).
(1.3) —
public; that is, its name can be used anywhere without access
restriction.

As you correctly observed, only member functions (including constructors and destructors) and friend functions and classes may access you're privates. That's the purpose of friends: they provide an exception (not std::exception) to the encapsulation mechanism.
Now you may think about whether this breaks encapsulation or actually stabilizes it.

if you want to access private member, you'd better use a public function like:
class a {
private:
int m;
public:
int getM() {
return m;
}
};

Your use of the phrase not by the object of that class makes me think that you are unclear on the access rules. The access rules don't apply to the objects but who can access member variables and member functions of the objects.
A member variable of a class can be accessed in a function -- which can be a member function of the class, a member function of another class, or a global function.
It can also be accessed in the global space, e.g. to initialize a global variable.
A friend declaration in a class changes the default access rules that are in place by use of private, protected, and public access specifiers.
A function declared a friend of a class can access all the members of all instances of the class.
The answer by songyuanyao cites the section of the standard that provides more details on the subject.

This function should be public, so that you can access it through main().
void print(){
/**print or return your private variable here**/
}

Related

are copy and move constructors automatic friends?

We can access private variables of another class when we define copy or move constructors. Does C++ make them friend to each other automatically?
For example:
my_str::my_str(my_str&& m)
{
size_ = m.size_; //accessing private variable another my_str class
buff_ = m.buff_; //accessing private variable another my_str class
m.buff_ = nullptr;
m.size_ = 0;
}
It is not considered friend, but yes, any member function of class my_str can access private members of all instances of type my_str, not just the this instance:
class my_str {
void foo(my_str& other) {
// can access private members of both this-> and other.
}
static void bar(my_str& other) {
// can access private members of other.
}
};
The general idea behind it is to allow 2 or more objects of the same type to interact without having to expose their private members.
Member functions of the class itself always have access to the private members, no matter whether the member function is defined in-class or out-of-class and no matter whether it is a special member function such as a copy/move constructor.
Therefore they are not friend of the class, because that doesn't make any sense. They are already part of the class. Still, they have access to all private members, not because they are friends, but because they are part of the class.
If it wasn't possible to initialized members in a constructor (because they are inaccessible), then the whole concept of member accessibility would be pointless. (How would you initialize the member?)
Also, accessibility is not in any way a matter of the object on which a member is accessed. Accessibility is a matter only of where in the code a name (the name of the member) is used. If a function can access the member of one instance of a class, then it can also access the member of another instance of the same class.

Public member of class and its access

Can we use public data member or member function in function which is declared in program but that are not member of that class ?
If the non-member function in question has an object on which to invoke the member functions, then yes - that's the idea with public members. For example:
class X
{
public:
void f() { }
int n_;
};
int main()
{
X x; // an actual object/variable of type X
x.f(); // can access public members
x.n_ = 3;
}
this is possible by using friend function concept. any function that is not member function of that class then we can declare this function with friend keyword as friend function. now by using this friend function we can access all private, protected, public data members with the help of object of that class.
Public data members of a class can be accessed by any function.
Public member functions of a class can be called by any function.
That is sort of the purpose of making class members public.
Naturally, there are other conditions (e.g. a function that calls a non-static public member function generally requires access to an instance of the class i.e. an object). Such conditions, if not met, will typically prevent code compiling or result in undefined behaviour - but that is unrelated to the question of whether a member is public or not.

Why can't a PRIVATE member function be a friend function of another class?

class x
{
void xx() {}
};
class y
{
friend void x::xx();
};
This results in an error like
error: friend function 'xx' is a private member of 'x'
Why can't I declare a private member function to be a friend of another class?
[class.friend]/9:
A name nominated by a friend declaration shall be accessible in the
scope of the class containing the friend declaration.
The reason is quite simple; private members shall obey a clear and definite rule:
A member of a class can be
private; that is, its name can be used only by members and friends of the class in which it is declared.
Allowing private members to be named in declarations inside unrelated classes would violate this rule: it enables another class to depend on an implementation detail without being explicitly allowed to. This becomes problematic, for instance, when changing a private member's name, type or signature, or removing it entirely; that's intended not to break the interface of that class.
This can be circumvented by making the entirety of x a friend of y:
class x {
void xx() {}
};
class y {
friend x;
};
Demo.
The idea of making x::xx private is supposed to be that x::xx is an implementation detail that other classes should not be relying on. It doesn't just mean that x::xx cannot be called by other classes, it means, or rather it should mean, that e.g. renaming x::xx to x::xy shouldn't break anything other than the class itself, and the class's friends.
In your case, renaming x::xx to x::xy would cause class y to have an error, even though it is not a friend of x.
A way to avoid that is to make y a friend of x, so that y can access x's private members. It can then declare x::xx as a friend.
(Note: the more direct answer to the question "Why does the compiler not allow this?" is "Because the standard does not allow this.", which naturally leads to the follow-up question "Why does the standard not allow this?". I'm attempting to answer that follow-up question.)

Is a local class in a method of a class a friend of this class?

I have an outer class A. It has a method A::fun. In this method, it has a local or inner class B. My question is: Is B a friend of A?
I think it is not. Is it right? If so, I think let class B a friend of A is very beneficial since B can access to A's private and protected members. And moreover, sinceB is local in a methods, it is not accessible by others and thus safe as a friend of A. How to work around to let B access to A's private and protected members?
No they are not friends.
But local classes have the same access to the names outside the function as the function itself.
The standard says :
9.8 Local class declarations [class.local]
A class can be declared 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 shall not odr-use (3.2) a variable with automatic storage duration from an enclosing scope.
The big difference to take in count is that your local class will only be accessible inside the function.
But after that :
A friend of a class is a function or class that is given permission to use the private and protected member names from the class.
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. That is, it can access to protected and private members of the class the function belongs.
No they are not friends. But does it matter?
Not really! consider these facts:
Within the member function you will always have access to the members of the class to which the function belongs.
You cannot access the local class anywhere beyond the function.
So it hardly matters if they are friends or not. You are always going to be referring the outer class members inside its member function.
Online Sample:
class A
{
int i;
void doSomething()
{
class B{public: int ii;};
B obj;
obj.ii = i;
}
};
int main()
{
return 0;
}
This compiles in Clang:
class A {
typedef int Int;
void fn();
};
void A::fn() {
class B {
Int i;
};
}
The inner class has access to A's private members, but not because it is a friend, but because it is considered a member. Since members of a class have access to private members, this includes inner classes as well as local classes of member functions.
See [class.access]p2.

File scope and access rules

I saw something like the following in a IKM test, the code is in a single file:
class A{
public:
int a;
A();
protected:
int x;
private:
int y;
};
void ARandomFunction(){
//Implementation
}
which variables of class A can ARandomFunction() access? Generally speaking what can be accessed if the decalarations are all in the same file?
Those variables will be per-instance (non-static member variables), so you first need to create an object to access them. Only public members can be accessed from a free-standing function unless the function is declared friend of that class in which case all members can be accessed.
That said it doesn't matter if they are in the same file or not. Once the class definition is visible where the function is implemented the members can be accessed.
Being in the same file changes nothing, your function can only access a as it is public and your function is not a member of A (for the private members) nor a sub class of it (for the protected members).
To my knowledge, using your above example ARandomFUnction can access the public variables and functions regardless of inheritance. THe protected variables can only be accessed if ARandomFunction is contained in a class that inherits from or is a member of class A. Private variables and methods can only be accessed from the same class.