This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
why private value of the obj can be changed by class instance?
Consider the following (partial) code:
class Group {
private:
int id;
public:
void set_id(int);
int get_id();
bool operator==(const Group&);
};
bool Group::operator==(const Group& g) {
if(g.id == this->id) { /* id is private? */
return true;
}
return false;
}
The code compiles and results seem proper. However, in the if part of the operator overloading implementation, we are directly accessing the private member of its argument - const Group& g, but isn't such an access invalid?
Your operator== is a member of your Group class. Member functions can access any private members of that class, not only for this, but for any instance they can access.
If you think about it this behaviour is necessary, because otherwise access control would make methods for interaction of two or more instances (swap, copy constructors, operators) impossible, unless the object has a public accessor to any member variable, which is used in such a method. Often enough that isn't desirable from a design point of view. Furthermore it would raise the bar for access control to high ("if I simply make that member public, I can spare me the pain...").
Concluding this code is perfectly valid (although I don't see why the if is necessary, compared to simply using return g.id == this->id;)
Access qualifiers are not controlling access on the instance level, but on the type level. Any member function of a instance of type T can access all the private members of any other instance of the very same type T.
Since the operator== is a member function it can access all the member variables of instances of the class it's member of.
No, because operator== is a member of Group. It's right there in the function name. That means it can access the private members of any object of that class.
If you tried to write it as a free function, that would not have compiled:
bool areEqual(const Group& g1, const Group& g2) {
return g1.id == g2.id;
}
Related
We just started talking about classes in my intro to CS class and I am a bit lost on how to know when a variable is private or not. We had a lab today and this is what the .h file contained:
(the class containing the below code is called personType)
class PersonType {
public:
void print() const;
//Function to output the first name and last name
//in the form firstName lastName.
void setName(string first, string middle, string last);
//Function to set firstName and lastName according
//to the parameters.
//Postcondition: firstName = first; lastName = last
string getMiddleName() const;
//function to return the middle name
//Postcondition: the value of middlename is returned.
string getFirstName() const;
//Function to return the first name.
//Postcondition: The value of firstName is returned.
string getLastName() const;
//Function to return the last name.
//Postcondition: The value of lastName is returned.
personType(string first = "", string middle = "", string last = "");
//Constructor
//Sets firstName and lastName according to the parameters.
//The default values of the parameters are null strings.
//Postcondition: firstName = first; lastName = last
private:
string firstName; //variable to store the first name
string middleName; //variable to store middle name
string lastName; //variable to store the last name
};
In int main, I declared an instance of the class called personType myself;
would the object myself have access to these private variables because it is apart of the same class containing the private variables? In what scenario would I not be able to access these private variables?
A member that is private can be accessed (without any or on any instance of the class) from within code written inside the class definition and all out-of-class definitions for members of the class.
That means in particular that where ever you implement PersonType's methods, they can access the private members in their body.
Any other code cannot access the private members by default (without a friend declaration).
In particular if you create an object PersonType person; in main you cannot use person.firstName. You can do the same in the implementation of PersonType::setName though and you also can use the implicit instance's firstName in PersonType::setName's implementation.
Accessibility is not specific to certain instances of classes. It is only a matter of the context in the code that the member names are used in. It doesn't matter whether the member is referred to as firstName, person.firstName, this->firstName, or any other way. In a member function, it also doesn't matter whether person is the current instance or some other instance of the class.
Each time the compiler encounters a name in your code it figures out to what declaration this name refers to. The accessibility check then looks at the context in which the name appeared and compares that to the result of the name-lookup to figure out whether the access should be allowed according to the rules above.
any method that belongs to PersonType will have access to the private variables, for instance string PersonType::getLastName() const
any other code, including main(), will not be able to access these variable.
void main()
{
PersonType myself;
myself.getLastName(); // OK!
std::cout << myself.lastName; // ERROR! lastName is private
}
Well, to know if it's private or not, you just have to check if it's in a private section of the class declaration :-)
But, expanding on that, an object (like myself) will always have access to its private members (and private members of other objects of that class, assuming it can see the actual object itself). Privates are generally(a) meant to prevent things outside the class from accessing them directly.
This prevention includes, for example, trying to do things like myself.firstName = "Pax" from your main function.
The usual way to get that level of access from outside is to provide getters and/or setters in the class. Using these allows you to do things like:
catch invalid attempts to change the variables; or
hide the internals of the class so that they can be changed without affecting the interface.
That is what those get* and set* methods in the code you posted are for, although I would have personally returned constant references for the getters - there's little point in copying something that may only be read:
const string &PersonType::getFirstName() const { return firstName; }
const string &name = pt.getFirstName(); // to just use it as is.
string name = pt.getFirstName(); // to get a modifiable copy.
(a) Things tagged as friend can bypass this protection but I won't cover that here, it would unnecessarily complicate the answer. You may also want to look into protected at some point, this allows sub-classes to access members (private members are off-limits to sub-classes) while still protecting them from things outside the inheritance hierarchy.
Each instance of personType has access to its own copies of the private variables of the class. It also has access to the private variables of other instances of the same type.
Non-personType variables and functions will not be able to see those variables. That includes variables of the type of any class you might derive from personType.
would the object myself have access to these private variables because it is apart of the same class containing the private variables?
This comes from a perspective that sees objects as having access to things. For some meanings of "access", this perspective can be useful. However, when the meaning of "access" involves access specifiers (public, protected, and private), it is more useful to view code as having access, rather than objects.
Code implementing a class has access to the private details of that class. Other code does not. In particular, the code in your main function has no access to any private details of any class.
(The friend keyword can change things, but it should not. If something declared a friend cannot reasonably be considered part of the implementation, then it likely has no business being a friend.)
would the object myself have access to these private variables because it is apart of the same class containing the private variables?
Yes. Each instance gets its own copy of the variables (unless you declare them static, but that's probably a topic for another time). So, if you have an object:
PersonType person;
There is conceivably these variables:
person.firstName
person.middleName
person.lastName
And, just to cover all my bases, these are available inside the class. So take the following function:
string getMiddleName() const;
The implementation of this function will have access to all private variables. So, for instance:
string PersonType::getMiddleName() const {
return middleName; // if this is called from person (that is, person.getMiddleName())
// then "middleName" here is person.middleName
}
Here, person.getMiddleName() can access person.middleName.
In what scenario would I not be able to access these private variables?
Most every other scenario where a function is not a part of the class PersonType. However, I will give some examples for the sake of clarity.
int main() {
PersonType person;
// bad
person.middleName;
return 0;
}
Here, you can't access person.middleName because main() isn't a part of PersonType. It is main(), i. e. another function. A general rule of thumb is if it is not part of the class, you can't access private variable.
void function(PersonType person) {
person.middleName; // still can't do it
}
Here, function() is not part of PersonType, so it doesn't have access to middleName.
There is only one exception to this rule about not being able to access private variables outside the class, and that is friend functions. To create a friend function, you have to modify your header a bit:
class PersonType {
public:
friend void friendFunction(PersonType person);
//...
};
Now, friendFunction() can access private data members:
void friendFunction(PersonType person) {
person.middleName; // it's fine. We're friends
}
The most common use of friend functions is with a slightly advanced topic called "operator overloading", which your class will almost certainly go over eventually.
Anyway, in the mean time, think of it this way: Is it part of the class? It can access private members. Is it a friend of the class? It can also access private members. Is it anybody else? No, it can't access private data members.
As far as I can understand as new comer to C++, both intends to expose a private member to public. We can say like this:
// Make everything outside can see value of name
object.get_name(); // get method
object.name(); // return member by ref to get
// Make everything outside can set value of name
object.set_name("Name"); // set method
object.name() = "Name"; // return member by ref to set
What's difference between those two way of accessing private member?
Why bother not to just create a public member if all I need is just to
get or set without doing anything else inside those functions?
With set_name, you can perform validation on the input, and throw exceptions as necessary. You can also update any other class members at the same time.
If you return a reference, you lose control of what can be set since the member can be modified through the reference. In fact, you may as well have the member variable public, as you point out.
you can have more control when you use a set function, rather than returning a reference to an internal class member (validation of input, exception throwing etc.).
class Foo{
std::string name;
public:
const std::string& get_name() const;
void set_name(const std::string&); // perform input validation inside set_name
};
If you expose the class member via a public function returning a reference to it you have removed the purpose of it being private in the first place.
Moreover, if the object is shared between multiple threads it may be necessary to synchronize access to the object's state. For that you would typically lock a mutex inside the object's functions.
class Foo{
mutable std::mutex mtx; // mutable so that it can be modified in const-qualified functions
std::string name;
public:
std::string get_name() const
{
std::lock_guard<std::mutex> lg{mtx};
return name;
}
void set_name(const std::string& str)
{
std::lock_guard<std::mutex> lg{mtx};
name = str;
}
};
By having the synchronization taking place inside get/set-functions the class itself handles the synchronization, without you having to worry about data races.
My suggestion is the following:
If your class is just a collection of independent variables (e.g. 3
dimensions of a vector or name, birth date and adress of a person)
then just use public members.
If your class has to maintain some
invariants (e.g. the allowed days in a date depends on the year and
month) use private members and public setter/getter methods that
enforce those invariants.
Sometimes, you also want to allow only read or only write access or you have "simulated" properties, which don't map directly to a specific member variable, but are calculated from them. In those cases you obviously also need separate setter and getter methods (or only one of them).
Finally, the only common case - I know of - in which you want to return
a non-const reference to a private variable is in containers, where
you acces an element by its index or key.
For example,
Number operator+(Number a, Number b) {
return Number(a.x + b.x);
}
Would this cause some kind of "unable to access private member error". I understand that if I don't pass by reference, the Number a, and Number b are copied on the stack and used in the body of the function. However, I don't see why they do not allow access to the originals' private members. How am I misunderstanding the concept of an object? Also how come friend and member function don't need to pass by reference?
operator+ is an unbound function, i.e. it is not a member of Number so, this is the rule, it has no implicit access to private members.
The rule is not affected by you passing Number objects by value or by reference. Access protection is applied to every access to a Number object, even if it is your private, stack-based copy.
There are at least three ways out:
declare Number operator+(Number, Number) a friend of Number
add a public getter for x so the variable is accessible.
implement the += operator as a member of the class and implement the free operator in terms of it: return Number(a) += b;
You're definitely misunderstanding something. 'Pass by reference', 'copied on stack' etc. have absolutely nothing to do with the access rules.
The code above is an error because operator+ is not a member of Number, and (presumably) it's not a friend of Number either. So it cannot access private members. That's all there is to it.
As many have answered operator + is not a member of Number class, it is a global variable. Consider a function Show:
void Show(const Number& numberObj) // const, by-ref is IMMATERIAL
{
std::cout<< numberObj.x;
}
and a method Show:
class Number
{
private:
int x;
public:
void Show()
{
std::cout << x;
}
};
Now, if you replace Show with any overloaded operator, taking 1 or 2 arguments - only the class-member can access the private data, and global implementation cannot.
For this, you need to make global Show a friend of class (in class declaration), and likewise any globally implemented operator.
What are the exact rules for deciding the access rights for the objects nested into the private sections of other objects?
For example, in the code snipped below, the proxy_t struct is nested into the private section of the abc_t, and yet its methods are available to the main function. Why does it compile at all?
#include <iostream>
#include <valarray>
using namespace std;
class abc_t{
private:
struct proxy_t{
proxy_t operator()(double& a, double& b){ __a=a; __b=b; return *this; }
double a(){ return __a; }
double b(){ return __b; }
private:
double __a, __b;
};
public:
abc_t( const size_t N ){
_a.resize(N,-101.);
_b.resize(N,-202.);
}
double a(size_t j){ return _a[j]; }
double b(size_t j){ return _b[j]; }
proxy_t operator[](const size_t j) { return _proxy(_a[j],_b[j]); }
private:
valarray<double> _a;
valarray<double> _b;
proxy_t _proxy;
};
int main(){
size_t n_elem=10;
abc_t abc(n_elem);
cout<<"direct: "<< abc.a(1)<<" "<<abc.b(1)<<"\n";
cout<<"proxied:"<<abc[1].a()<<" "<<abc[1].b()<<"\n"; // ain't proxy_t::aa() private?
//cout<<abc[1]; // doomed to fail
}
This line is the important one that I'm gonna talk about:
cout<<"proxied:"<<abc[1].a()<<" "<<abc[1].b()<<"\n";
When you call abc[1], this is a public method of abc_t. This is valid.
It returns a proxy_t. Although the declaration of this class (proxy_t) is not defined, you aren't actually using that return variable to create a new object. If you were to do the following, it wouldn't compile.
proxy_t p = abc[1];
It crashes with that because proxy_t is being declared, you are initializing a new object, however that type doesn't exist in that scope. Since you aren't actually declaring any variables of that type, nothing of proxy_t is being created in that scope (which would be illegal).
By proxy_t being private, that simply means you can't create any objects of that type anywhere except from within the abc_t class. However, it's being passed as a return value, which is valid -- no objects are being created/instantiated/declared, just an existing one is being passed.
Then the fun part. With classes, everything by default is private (unless specified otherwise). With structs, everything by default is public. Therefore, proxy_t::a() is public, and therefore CAN be used in main because main happens to have access to a proxy_t object.
You have defined the struct proxy_t as private, but the actual methods it exposes are public. My guess is that your compiler will not allow you to directly instantiate a proxy_t struct in main, but if you return one from class abc_t, it will allow you to call public methods on it.
Perhaps someone who knows the C++ standard can comment if this is correct behaviour for a compiler or not.
You're saying abc[1].a() which says go here:
proxy_t operator[](const size_t j) { return _proxy(_a[j],_b[j]); }
which is public and throws that 1 in for j. Then it returns
_proxy(_a[j],_b[j])
which is calling the private struct that you use to access the a() function
Since proxy_t is a private member to abc_t, no one except abc_t can use it (i.e. instantiate objects of this type). However, given an existing proxy_t, everybody can invoke its members - because they are public.
The standard is a bit dull here (or I'm looking at the wrong place), but this is my best finding (11.8):
A nested class is a member and as such has the same access rights as any other member. The members of
an enclosing class have no special access to members of a nested class; the usual access rules (Clause 11)
shall be obeyed.
Reading between the lines: Since a nested class is 'just' a member, usual access control is applied when somebody refers to this type (i.e. spells out proxy_t). But for access to members of proxy_t itself, no special access rules apply - if you managed to get a proxy_t object from a privileged source, you can access its members as if it wasn't a nested class.
I feel I have a bit of a hole in my understanding of the friend keyword.
I have a class, presentation. I use it in my code for two variables, present1 and present2, which I compare with ==:
if(present1==present2)
Here's how I defined the operator == (in class presentation):
bool operator==(const presentation& p) const;
However, I was told that using friend and defining it outside of the class is better:
friend bool operator==(presentation&, presentation&);
Why? What's the difference between the two?
Your solution works, but it's less powerful than the friend approach.
When a class declares a function or another class as friend it means that friend function or class have access to the declaring class' privates and protected members. It's as if the declared entity was a member of the declaring class.
If you define operator==() as a member function then just like with the friend case the member function has full access to the class' members. But because it is a member function it specifies a single parameter, as the first parameter is implied to be this: an object of type presentation (or a descendent thereof). If, however, you define the function as a non-member then you can specify both parameters, and this will give you the flexibility of comparing any two types that can cast into a presentation using that same function.
For example:
class presentation {
friend bool operator==(const presentation&, const presentation&);
// ...
};
class Foo : public presentation { /* ... */ };
class Bar : public presentation { /* ... */ };
bool operator==(const presentation& p1, const presentation& p2)
{
// ...
}
bool func(const Foo& f, const Bar& b, const presentation& p)
{
return f == b || f == p );
}
Lastly, this raises the question "why the friend declaration?". If the operator==() function does not need access to private members of presentation then indeed the best solution is to make it a non-member, non-friend function. In other words, don't give a function access privileges which is doesn't need.
In the first case, your function operator== is a nonstatic class member. It has therefore access to private and protected member variables.
In the second case, the operator is externally declared, therefore it should be defined as a friend of the class to access those member variables.
An operator implemented as a method, can only be called, if the left hand side expression is a variable (or a reference to the object) of the class, the operator is defined for.
In case of an operator== usually you are interested in comparing two objects of the same class. Implementation, as a method solves your problem here.
Imagine however, that you write a string class and you want an operator, to work in this scenario:
const char *s1 = ...
MyString s2 = ...
if(s1 == s2){...
To make the expression s1 == s2 legal, you have to define an opetator== as a function external to MyString class.
bool operator==(const char *, const MyString&);
If the operator needs an access to the private members if your class, it has to be a friend of your class.
In case of operators << and >>, that work on streams, you define an operator, whose left operand is a stream instance and the right one is your class, so they can't be methods of your class. Like in the example above, they have to be functions external to your class and friends, if the access to private members is required.
I like Benoit's answer (but I can't vote it up), but I figure an example wouldn't hurt to clarify it. Here's some Money code I have (assume everything else is placed right):
// header file
friend bool operator ==(const Money, const Money); // are the two equal?
// source file
bool operator ==(const Money a1, const Money a2)
{
return a1.all_cents == a2.all_cents;
}
Hope that helps.
Take a look at this sorta duplicate here: should-operator-be-implemented-as-a-friend-or-as-a-member-function
What is important to point out, this linked question is about << and >> which should be implemented as friends since the two operand are different types.
In your case it makes sense to implement it as part of the class. The friend technique is used (and useful) for cases where more than one type is used and often does not apply to == and !=.