C++ private members accessible? [duplicate] - c++

This question already has answers here:
can you access private member variables across class instances?
(2 answers)
Closed 9 years ago.
I have this project in our signals class which uses C++. I was tinkering with our instructors code when I saw this:
ListData::ListData(const ListData& newlist)
: Data(), nbNodes(newlist.nbNodes) {}
This is a "copy constructor" as he says, and should be roughly equivalent to the following:
ListData::ListData(const ListData& newlist){
Data = "";
//copy nbNodes of newList to current instance
nbNodes = newlist.nbNodes;
}
But what bothers me is that nbNodes is a private member. How could this constructor access the nbNodes of the passed newList if it's private?

An interesting thing about private members is that two objects of the same type can access each others private members freely. You can think of it as a class is always friends with itself. Since this is the constructor for ListData and newlist is also a ListData, you can access its privates just fine.
Here's an example of this:
#include <iostream>
class foo
{
public:
foo() { }
foo(std::string secret) : secret(secret) { }
void steal_secret(const foo& other) { secret = other.secret; }
std::string get_secret() { return secret; }
private:
std::string secret;
};
int main() {
foo f1("I'm actually a bar");
foo f2;
f2.steal_secret(f1);
std::cout << f2.get_secret() << std::endl;
return 0;
}
f2 happily and easily steals the secret from f1, despite it being private.
The reason for this being allowed is simply because private doesn't mean private to an object - it means private to a class. This eases the implementation of functions such as copy constructors that require doing some work to the internals of two objects of the same class.
The rule comes from the definition of private (ยง11/1):
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.
[...]
Note that it is defined in terms of classes and not objects.

The private keyword has class semantics not object semantics. So private members of an object of a class are accessible to other objects of the same class.

nbNodes is private to the ListData class, not to a particular instance of that class. So, inside the code of the class, you can see the private data of other instances of that class.
If it weren't so, every class would have to export "getters" for every single data member in order to perform copy construction and copy assignment.

A copy constructor is just like any other method: as you can access private members of a class from a method of that class, you can do the same with your copy constructor (else, how could you copy the state of an instance to the class to another one?).

Members with private visibility are members that can only be accessed within member functions of the same class they are members of, without restrictions on objects.
If function f() is a member function of class C, it can access the private members of any instance of C, not just those pointed by the implicit this pointer (which, of course, makes this valid for static functions as well, which do not receive a this pointer at all).

From C++ Standard, Chapter 11: Member Access Control:
private; that is, its name can be used only by members and friends of
the class in which it is declared.
That means a private member could be accessed by any members of that class
Here ListData::ListData(const ListData& newlist) is a copy constructor of ListData, which is a member function thus could access class ListData's private member.

Related

Why a class can see the private members of a parameter class?

Note that class x and y are two separate entities and you can not see their private data members from outside of their bodies.
It is known that from int main() I can not see the private member of class x or y.
My question in the following code in line 22:
Why class x can see the private members of class y ? (note here I am sending class y as reference not as a copy) isn't the referenced class y should be protected from strangers like class x ?
Note that the function getForeignNumber(const Player &r) inside class x is not a friend to class y!
#include<iostream>
class Account{
private:
int number{ } ;
public:
Account(int numberValue)
:number{numberValue}
{
std::cout<<"constructor is called"<<std::endl;
}
int getLocalNumber()
{
return this->number;
}
int getForeignNumber(const Account &r)
{
return r.number; // line 22
}
};
int main()
{
Account x{1};
Account y{2};
std::cout<<"get local number="<<x.getLocalNumber()<<std::endl;
std::cout<<"get foreign number x ="<<x.getForeignNumber(x)<<std::endl;
std::cout<<"get foreign number y="<<y.getForeignNumber(y)<<std::endl;
std::cout<<"Hello world"<<std::endl;
return 0;
}
First of all, you are confusing instances of a class with the class. x and y are two instances of the same class Account.
Your analogy isnt sound. Two instances of the same class aren't "strangers". They can access all the internals of each other. Thats how access works.
From cppreference:
All members of a class (bodies of member functions, initializers of member objects, and the entire nested class definitions) have access to all names the class can access. A local class within a member function has access to all names the member function can access.
In other words, access is per class not per instance. If x would not be able to access ys private members it would be impossible for example to write a copy constructor (without getter methods, which would be silly).
PS: By the way, "see" is the wrong word. There are certain circumstances where you can "see" that there is a private member from outside of the class, you just cannot access it. One such situation is when the name of a private method shadows that of a publicly inherited method https://godbolt.org/z/Kzf5KWv4W. Hence, even colloquially "see" is the wrong word for access.
The function getForeignNumber() can see private members of class Account because getForeignNumber() is a member of class Account.
private members are hidden from entities that are outside the class, not from other instances (objects) of the same class.

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.

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

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**/
}

Do Sub-Classes Really Inherit Private Member Variables?

Basically as far as I know, when you create a base class with a public, protected, and private section and variables/functions in each the public and protected sections will get inherited into the appropriate section of the sub-class (defined by class subclass : private base, which will take all public and protected members of base and put them into public, changing the word private to public puts them all in public and changing it to protected puts them all into protected).
So, when you create a sub-class you never receive anything from the private section of the previous class (the base class in this case), if this is true then an object of the sub-class should never have it's own version of a private variable or function from the base class correct?
Let's run over an example:
#include <iostream>
class myClass // Creates a class titled myClass with a public section and a private section.
{
public:
void setMyVariable();
int getMyVariable();
private:
int myVariable; // This private member variable should never be inherited.
};
class yourClass : public myClass {}; // Creates a sub-class of myClass that inherits all the public/protected members into the
// public section of yourClass. This should only inherit setMyVariable()
// and getMyVariable() since myVariable is private. This class does not over-ride any
// functions so it should be using the myClass version upon each call using a yourClass
// object. Correct?
int main()
{
myClass myObject; // Creates a myClass object called myObject.
yourClass yourObject; // Creates a yourClass object called yourObject
yourObject.setMyVariable(); // Calls setMyVariable() through yourObject. This in turn calls the myClass version of it because
// there is no function definition for a yourClass version of this function. This means that this
// can indeed access myVariable, but only the myClass version of it (there isn't a yourClass
// version because myVariable is never inherited).
std::cout << yourObject.getMyVariable() << std::endl; // Uses the yourClass version of getMyVariable() which in turn
// calls the myClass version, thus it returns the myClass myVariable
// value. yourClass never has a version of myVariable Correct?
std::cout << myObject.getMyVariable() << std::endl; // Calls the myClass version of getMyVariable() and prints myVariable.
return 0;
}
void myClass::setMyVariable()
{
myVariable = 15; // Sets myVariable in myClass to 15.
}
int myClass::getMyVariable()
{
return myVariable; // Returns myVariable from myClass.
}
Now, in theory based on what I think, this should print:
15
15
Due to it simply always using the myClass version of the functions (thus using the myClass myVariable). But, strangely, this is not the case. The result of running this program prints:
15
0
This makes me wonder, are we actually not only inheriting myVariable, but do we also have the ability to mess around with it? Clearly this is creating an alternate version of myVariable somehow otherwise there wouldn't be a 0 for the myClass version. We are indeed editing a second copy of myVariable by doing all this.
Can someone please explain this all to me, this has torn apart my understanding of inheritance.
Basically as far as I know, when you create a base class with a public, protected, and private section and variables/functions in each the public and protected sections will get inherited into the appropriate section of the sub-class (defined by class subclass : private base, which will take all public and private members of base and put them into public, changing the word private to public puts them all in public and changing it to protected puts them all into protected).
There's a bit of confusion in this statement.
Recall that inheritance is defined for classes and structs in C++. Individual objects (ie. instances) do not inherit from other objects. Constructing an object using other objects is called composition.
When a class inherits from another class, it gets everything from that class, but the access level of the inherited fields may inhibit their use within the inheritor.
Furthermore, there are 3 kinds of inheritance for classes: private (which is the default), protected, and public. Each of them changes the access level of a class properties and methods when inherited by a subclass.
If we order the access levels in this manner: public, protected, private, from the least protected to the most protected, then we can define the inheritance modifiers as raising the access levels of the inherited class fields to at least the level they designate, in the derived class (ie. the class inheriting).
For instance, if class B inherits from class A with the protected inheritance modifier:
class B : protected A { /* ... */ };
then all the fields from A will have at least the protected level in B:
public fields become protected (public level is raised to protected),
protected fields stay protected (same access level, so no modification here),
private fields stay private (the access level is already above the modifier)
"When you create a sub-class you never receive anything from the private section of the [base class]. If this is true then an object of the sub-class should never have it's own version of a private variable or function from the base class, correct?"
No. The derived class inherits all the members of the base class, including the private ones. An object of the inherited class has those private members, but does not have direct access to them. It has access to public members of the base class that may have access to those members, but it (the derived class) may not have new member functions with such access:
class yourClass : public myClass
{
public:
void playByTheRules()
{
setMyVariable(); // perfectly legal, since setMyVariable() is public
}
void tamperWithMyVariable()
{
myVariable = 20; // this is illegal and will cause a compile-time error
}
};
myObject and yourObject are two different objects! Why should they share anything?
Think about it that way: Forget about inheritance and suppose you have a class Person with private int age; and public void setAge (int age) {...}. You then instantiate two objects:
Person bob;
Person bill;
bob.setAge(35);
Would you expect Bill to be 35 now, too? You wouldn't, right? Similarly, your myObject doesn't share its data with yourObject.
In response to your comment:
The class yourClass inherits from myClass. That means that both yourObject and myObject have their own myVariable, the latter obviously by definition, the former inherited from myClass.
Physically, every single member( including member functions) of base class goes into the subclass. Doesn't matter if they are private. Doesn't matter if you inherit them publically/protected-ly/privately. So in your example, yourClass contains all three of getMyVariable(), setMyVariable() and myVariable. All this is pretty simple, okay?
What matters is how we can access them. It is like when a file is deleted on your system. So, you should first understand the difference between a member being not there and a member being there but inaccessible. Assume for now that all inheritance takes place publically. Then, all public members of base class are public in derived class, protected members are protected and private members are inaccessible. They are inaccessible and not non-existent because there can be some member functions in protected and public sections in base class which access the private members of base class. Thus, we need all those private members of base which are accessed by public and protected member functions of base, for their functionality. Since there is no way that we can determine which member is needed by which member function in a simple manner, we include all private members of the base class in derived class. All this simply means that in a derived class, a private member can be modified by only through the base class' member functions.
Note: every private member has to be accessed, directly or indirectly [through another private member function which in turn is called by a public/protected member function] by a public/protected meber function, else it has no use.
So, we know till now that a private member variable of base class has its use in derived class i.e. for the functionality of its public/protected member functions. But they can't be accessed directly in base class.
Now, we turn our attention to private/public inheritance. For public inheritance, it means that all the accessible members of base class (that is, the public and protected members) can not be at a level more permissive than public. Since, public is the most permissive level, public and protected members remain public. But at protected and private inheritance, both become protected and private in the derived class, respectively. Inthe latter case, since all these members are private, they can't be accessed further in the hierarchy chain, but can be accessed by the given derived class all the same.
Thus, the level of each base class member in derived class is the lesser of their level in derived class () and the type of inheritance (public/protected/private).
Same concept applies to the functions outside the class. For them private and protected members are inaccessible but they do exist and can be accessed by the public member functions.
And taking your case as a final example, setMyvariable() and getMyVariable() can access myVariable in the derived class. But no function specified in derived class can access myVariable. Modifying your class:
class myClass
{
public:
void setMyVariable();
int getMyVariable();
private:
int myVariable;
};
class yourClass : public myClass
{
public:
// void yourFunction() { myVariable = 1; }
/*Removing comment creates error; derived class functions can't access myVariable*/
};
Further: you can add exceptions to the type of inheritance too e.g. a private inheritance except a member made public in derived class. But that is another question altogether.
You never call myObject.setMyVariable(), so myObject.getMyVariable() will not return 15.
private does not imply static.
After:
class yourClass : public myClass {};
there is still only one member variable. But there are two ways of accessing it by name: myClass::myVariable, and yourClass::myVariable.
In these expressions, the class name is known as the naming class. The second key thing to understand is that access rights apply to the combination of naming class and member name; not just to the member name and not to the variable itself.
If a member is mentioned without explicitly having the naming class present, then the naming class is inferred from the type of the expression on the left of the . or -> that named the member (with this-> being implied if there is no such expression).
Furthermore, there are really four possible types of access: public, protected, private, and no access. You can't declare a member as having no access, but that situation arises when a private member is inherited.
Applying all this theory to your example:
The name myClass::myVariable is private.
The name yourClass::myVariable is no access.
To reiterate, there is only actually one variable, but it may be named in two different ways, and the access rights differ depending on which name is used.
Finally, back to your original example. myObject and yourObject are different objects. I think what you intended to write, or what you are mentally imagining is actually this situation:
yourClass yourObject;
myClass& myObject = yourObject;
// ^^^
which means myObject names the base class part of yourObject. Then after:
yourObject.setMyVariable();
the variable is set to 15, and so
std::cout << myObject.getMyVariable() << std::endl;
would output 15 because there is indeed only one variable.
This may help
#include<iostream>
using namespace std;
class A
{
int b;
};
class B : private A
{
};
int main()
{
C obj;
cout<<sizeof(obj);
return 0;
}

Confusion with copy constructor and private member

Suppose I have the following class:
class Test
{
int num;
public:
Test(int x):num(x){}
Test(const Test &rhs):num(rhs.num+1){}
};
int main()
{
Test test(10);
Test copy = test;
}
The num in the copy should be 11, and my question is about inside the copy constructor, why can we access the private member num of test using num to initialize the num in the copy? What is confusing me is that if you type cout<<test.num<<endl, of course it's wrong because you are trying to access the private num, but if you pass the test by reference to the copy constructor, it works, can anybody tell me what is going on here?
Private members are private to the class itself, not the instances of the class.
Access limitations are per-class, not per-object.
"private" means -- can only be accessed from within the same class.
"protected" means -- can be accessed from within the same class, and can also be accessed from within derived-classes (in derived classes, protected non-static members can only be accessed through variables with derived class type).
"public" means -- can be accessed by anything.
The point of access limitations is to limit the region of code that has to be inspected in order to understand where the values are used, rather than to stop code from using the values.
private doesn't mean private to the object instance. It means private to that class. An instance of a class T can access private members of other instances T. Similarly, a static method in a class T can access private members of instances of T.
If private restricted access to only the individual instance, it would make objects non-copyable, since as you pointed out, the copy constructor would not be able to read data from the original instance.