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.
Related
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**/
}
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.
This answer seems to suggest it should work so why does my example kick up a compiler error:
class Class1
{
protected:
long m_memberVar;
};
class SubClass1: public Class1
{
public:
void PrintMember(Class1 memberToPrintFrom)
{
Console::Write("{0}", memberToPrintFrom.m_memberVar); // <-- Compiler error: error C2248: 'BaseClassMemberAccess::Class1::m_memberVar' : cannot access protected member declared in class 'BaseClassMemberAccess::Class1'
}
};
[Edit] - changed subclass to a public inheritance on Need4Sleep's suggestion but it makes no difference.
In this answer I'll assume that you used public inheritance in your code (which was missing from the question).
[C++11: 11.2/1]: If a class is declared to be a base class (Clause 10) for another class using the public access specifier, the public members of the base class are accessible as public members of the derived class and protected members of the base class are accessible as protected members of the derived class. If a class is declared to be a base class for another class using the protected access specifier, the public and protected members of the base class are accessible as protected members of the derived class. If a class is declared to be a base class for another class using the private access specifier, the public and protected members of the base class are accessible as private members of the derived class.
This covers the case where you're accessing a member of the same object.
However, it's a little curiosity of protected member access that in order to access a protected member of another object, it has to be located within the definition of the same type or a more derived type; in your case, it is in a less-derived type (i.e. a base):
[C++11: 11.4/1]: An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class (11.2) As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C. If the access is to form a pointer to member (5.3.1), the nested-name-specifier shall denote C or a class derived from C. All other accesses involve a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall be C or a class derived from C.
That is, you'd have to run this code from within a Class1 member function.
Bjarne mentions this in his book The C++ Programming Language (Sp. Ed.) on page 404:
A derived class can access a base class' protected members only for objects of its own type [...] This prevents subtle errors that would otherwise occur when one derived class corrupts data belonging to other derived classes.
Protected members of a base class can be accessed by the derived class only through its self (this) or through another object of the same class, but not generically through the base class. That is the access, and the purpose is that the use of the member is considered restricted to the implementation detail of the class, and as your class is dealing with the base class, it would not know the meaning of the member in this particular case.
There is a workaround you can use to get access which is to provide a protected getter and setter in the base class, often static, that will fetch it or set it for you.
class Class1
{
protected:
long m_memberVar; // could even be private
static long getMemberVar( Class1 const& inst )
{
return inst.m_memberVar;
}
static long setMemberVar( Class1 & inst, long val )
{
inst.m_memberVar = val;
}
};
And now derived classes (but not general classes) can use the getter and setter methods.
You can also take advantage of the fact that a derived object can be converted to the base object type and that an object can access protected and private members of any object of it's own type. If the base object has an assignment operator that can guarantee all desired members are correctly copied, you can do something like this:
class Class1
{
protected:
long m_memberVar;
};
class SubClass1 : public Class1
{
public:
void PrintMember(Class1 memberToPrintFrom)
{
SubClass1 tmpSC;
auto tmpC1 = dynamic_cast<Class1*>(&tmpSC);
*tmpC1 = memberToPrintFrom;
cout << tmpSC.m_memberVar << endl;
}
};
This isn't efficient, but will allow you to get at the base class member without having to add functions to the base class. This is using object slicing to replace the base portion of the temporary derived object with the passed base object's values.
Simplification of the code to express the concept:
class classA
{
public:
private:
int a;
seta(int x);
};
//local prototype
void somefunction();
int main()
{
classA object; //create an object of the class
somefunction(object);
return 0;
}
void somefunction(classA &object)
{
object.seta(5);
}
}
If I move seta() to the public section of the class there is no error and it executes.
However, if I move seta() to the private section, I get the following error:
error C2248:
'anonymous-namespace'::classA::seta' : cannot access
private member declared in class 'anonymous-namespace'::classA'
If the function is private and only this class is calling it, why is there an issue?
EDIT I am passing the object from main to the local function
The function that is calling seta() is not part of classA, so this is an error; that's the very definition of private. If you were to make somefunction() a member of classA, or declare it to be a friend of classA, then this would work.
The function somefunction() is not a member function of classA. It's a function with global scope and cannot access the private function seta(), just as main() cannot access the private function seta().
This has nothing to do with "local functions" (functions defined inside other functions). This is simply about public and private members.
If a member is private, then it can only be accessed by other members of that class, or by explicit friends of the class.
private means that only member functions and friends can access it. Both must be listed in the class declaration, but are not:
class classA
{
public:
private:
int a;
seta(int x);
};
Being in the same file doesn't make the function a part of the class -- only the class declaration is used to determine what has access.
Private members can only be accessed by it's members and it's friends. Also every member function in C++, should have a return type. With that said -
void main() // 1
{
classA object; //2
somefunction();
}
Return type of main should be int.
Scope of object is only in main and cannot be accessed in somefunction with out explicitly passing it to the function.
On your Edit:
You are passing object to somefunction(classA) by value. So, a copy of the object ( main scoped) is made to somefunction scoped object. Though they bear the same name, both are different.
void somefunction(classA object)
{ // ^^^^^^ Is a copy of the parameter passed.
object.seta(5); // This call isn't actually modifying the original parameter passed.
}// life time of argument,object, ends here.
You should pass it by reference instead if you wish to modify parameter passed itself.
Firstly, to answer your primary question:
If the function is private and only this class is calling it, why is
there an issue?
The issue is that private class members can only be invoked by other members of that class. The function somefunction() is not a member of classA and therefore does not have access to private member seta().
As an aside, you should also think carefully about what you're doing when passing object to somefunction() from main. You're passing object by value, so you're creating a copy of object scoped to somefunction() which will be destroyed as soon as somefunction() terminates. IS that what you want?
I suspect that you're intending to pass object to somefunction() from main by reference, in which case you need to declare somefunction() as
void somefunction(classA &object)
seta(int x) is a private member of ClassA, so only ClassA or a friend class of ClassA can access to this member. somefunction() is none of them.
I have created a class called "ShortestTime". I have some functions within it that are not member functions, but I would like them to be able to access my member variables.
ie. I have a function that sorts a List that is a public member variable, but it doesn't have access to this member variable.
I have read something about "friend" but was unable to get this to work. How do I solve my problem?
Thanks for the help,
Robin
There are ways you could use friend to solve your problem but we would need to see sample code.
But my personal approach would be to add a function to ShortestTime that sorts your private member.
ShortestTime::SortInterals()
{
//sort private stuff
}
Is there a reason that won't work?
It completely depends on what language we are talking about here. Since you are talking about "friend" functions, I am going to assume you are talking about c++.
So basically, a friend function is just a normal function which has access to private and protected members of a class in c++. For example..
int abc(myclass a)
{
...
}
class myclass
{
int someprivatemembers;
public:
function myClass() { ... }
friend int abc(myclass);
}
Now, in the above example, the function abc will have access to someprivatemembers of object a passes to it, because it is declared as a "friend" of the class.
I have created a class called "ShortestTime". I have some functions within it that are not member functions, ...
No you don't :-). All the functions within a class are member functions by definition. You might well have some functions without the class - they would not be member functions.
but I would like them to be able to access my member variables.
ie. I have a function that sorts a List that is a public member variable, but it doesn't have access to this member variable.
Yes it does. You've said you have a public member variable List:
class X
{
public:
List identifier_;
};
All functions have access to the list, irrespective of whether they're member functions or not.
I have read something about "friend" but was unable to get this to work. How do I solve my problem?
The only situation in which you might find you need friend, and hence the one that might apply despite the statements above, is akin to...
class X
{
public:
private:
List identifier_;
};
void some_non_member_function()
{
X x;
x.identifier_; // HOW TO GET ACCESS...?
}
To grant some_non_member_function() access to a private data member, you can...
make it a friend of the class
class X
{
friend void some_non_member_function();
};
void some_non_member_function()
{
X x;
x.identifier_; // NOW OK
}
make it a member function
class X
{
public:
void some_non_member_function()
{
X x;
x.identifier_; // NOW OK
}
};