Scope of private variables - c++

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.

Related

C++ Difference between method returning member by ref and get-set method

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.

C++ function parameters and classes

I was just wondering if you could explain to me how functions with parameters work.
I've been following tutorials etc but they do not seem to explain how the code works to get the output. Heres an example:
#include <iostream>
using std::endl;
using std::cout;
using std::cin;
using std::string;
class stan
{
public:
void setName(string x)
{
name = x;
}
string getName()
{
return name;
}
private:
string name;
};
int main()
{
stan con;
con.setName("Bruce Almighty");
cout << con.getName() << endl;
}
I do not get how we get from the public string name to the private string name. What I'm saying must sound really confusing but I don't know how else to put it, I would just like to be able to understand how this code works.
Thanks to anyone that helps, it means alot
Program starts at function main.
It declares a local variable con of type stan.
Method setName of object con is called with argument "Bruce Almighty".
Method with heading void setName(string x) starts executing. Parameter x takes the value of the corresponding argument ("Bruce Almighty").
Private member name of this object is set to the value of parameter x ("Bruce Almighty").
Method setName returns to the point it was invoked.
cout represents console output.
To apply operator <<, con.getName() needs to be evaluated. Method getName of object con is called with no arguments.
Method with heading string getName() starts executing. No parameters involved.
Value of private member name of this object is returned ("Bruce Almighty").
Method getName returns to the point it was invoked with value "Bruce Almighty".
cout uses this value and produces it in the console.
The same cout object produces endl value in the console. endl make a new line to be created in the console.
http://www.cplusplus.com/doc/tutorial/classes/
private members of a class are accessible only from within other
members of the same class or from their friends.
protected members are accessible from members of their same class and from their friends,
but also from members of their derived classes.
Finally, public members are accessible from anywhere where the object is visible.
Basically, a private member is something that ONLY a class function can access. So "string name" can only be read/write from class functions. Public functions/variables can be called from outside the class, the example you gave is "setName" and "getName"
So in order to write or read the private string, your code uses the public functions you created.
Basic steps:
con.setName("Bruce Almighty");
calls the setname function and passes the string "Bruce Almighty" to it.
void setName(string x)
receives the string "Bruce Almighty" that you sent, and calls it x.
name = x;
assigns the value of x, which is "Bruce Almighty", to the variable name.
con.getName()
asks for a value from the getName function.
string getName()
declares the getName function as one that returns a string.
return name;
takes the string held in the variable name, which setName set to "Bruce Almighty" and returns it to the caller, which sends it to cout for outputting.
setName is somebody who helps you to deliver your string, "Bruce Almighty" to the private name field in the stan village.
You are saying, "Hey setName, I am going to pass "Bruce Almighty" argument as your parameter x. I don't care how you do it, but simply deliver it to the private name field!
setName says, "Ok, I got it, you mean my x parameter is Bruce Almighty right?"
You say, "Yes right!"
setName says. "Ok, I am done. You don't need to know how I did it. This is what we call abstraction. You simply order, but you don't need to understand how I did it. However, just in case you want to know, I did it by using the assignment operator =. I placed the private name field on the left side, and my parameter x on the right side. Because you provided Bruce Almighty to my parameter x, it is assigned to the private name field. Boom!"
Inside a class definition you can access data members using just their name. E.g. inside setName body the names of all members are in scope, thus also the private data member name. In this way the statement:
name = x;
assigns the value of x (the argument of setName) to name, which is the private data member.
You must be careful when naming members, though, as name clashes may arise if a local variable is named the same as a member. You can avoid them either prefixing your members with this-> like:
this->name = x;
or using a naming convention such as giving to any data member's name a prefix:
m_name = x; // "m_" stands for "member"
...
private:
string m_name;
this is a C++ keyword representing a pointer to the object on which you invoke your methods (i.e. member functions). It can be used to refer to that object inside a class definition. Thus this->name means "the member called name inside the object pointed by the pointer this"

Difference between Class A and class Class1

I am trying to do this C++ tutorial. I am a beginner in C++ programming. I don't get why they use setValue and getValue in class Class1 and not setClass1. In the other tutorial they use setA and getA in the class class Class1. Here are the codes:
class Class1 {
int i;
public:
void setValue( int value ) { i = value; }
int getValue() { return i; }
};
the second code is:
class A{
int ia;
public:// accessor method because they are used to access a private date member
void setA ( const int a);
int getA ()const;
int getA ();
};
Please help...
The names are arbitrary, you can use any function names you wish (subject to language rules, of course).
However, although you can use xyzzy() and plugh() as getter and setter, it's not really a good idea.
You should use something that indicates the intent of the call, such as getTemperature() or setVelocity(). And these don't even have to map one-to-one to internal fields since encapsulation means the internal details should not be exposed.
By that, I mean you may have a getTemperatureC() for returning the temperature in Celsius even though the internal field is stored as Kelvins:
double getTemperatureC(void) { return kelvins - 273.15; }
void setTemperatureC(double t) { kelvins = t + 273.15; }
(or a getter/setter may use arbitrarily complex calculations).
Using getA() for a class A may well cause you trouble when you create class B to inherit from A but this is outside the scope of the language. But it's good programming practice to follow the guideline above (functions should indicate intent rather than internals).
I was confused on why they use the same name in get and set with the class name, and different get and set name on the other class. Will the set and get names affect the code?
The answer is No.
getter and setter are usually called accessor and mutators in a class. They are just member functions named according to some convention, easy for people who read the code to understand the purpose of those functions, so it is like common sense to name those member function starting with get if you try to access the member variables and starting with set if you try to change some member variables. The names can be any valid identifier.
So setValue or setA are just identifiers for those member functions. It will not affect the code.
Meanwhile, different class can have the same named getter or setters since those function names are in different class scope.

implementing an accessor for a static variable in c++

I'm a CS student and right now we're learning about inheritance. For our assignments, the teacher gives us a main.cpp file and a class header. We're expected to create a .cpp implementation of the header without altering the given files. I've done most of it, but here's what I can't implement:
// File: employee.h
class Employee : public Person
{
private:
static Company company;
public:
static Company GetCompany();
static void SetCompany(const Company& company);
}
It's the [static void SetCompany] that I'm unable to work with. Normally in the implementation I'd just do
// File: employee.cpp
void Employee::SetCompany(const Company& company) { this->company = company; }
but I get the error "'this' may only be used inside a nonstatic member function". I'm not really sure how else I'm supposed to assign the variable, and it was never addressed in class. Any help would be appreciated. Just note that this is pretty much the format I'm expected to keep, so hopefully any advice won't stray too much. Anyway, thanks in advance and let me know if anything needs to be clarified... or if I'm just being blind and/or stupid about this.
To access a static field, use Employee::company, as you cant use this because it is meant to refer to an instance of a class.
Your setter will become
void Employee::SetCompany(const Company& company) {
Employee::company = company;
}
But if you try to simply replace your setter, your compiler will throw an error, saying that it doesn't know Employee::company. Because it is not instantiate. You need, in your .cpp file, as you would do with a function to declare your field with
Company Employee::company;
To expand on the earlier comment, you can refer to static members with their full name, for example Employee::company. So, you should be able to fix your example by simply changing the function to this :
static void SetCompany(const Company& company) { Employee::company = company; }
This is because static member variables are independent of a particular instance of the class. The this keyword refers to the specific instance of the class. So, by changing a static member, all instantiations of the class have this change.
For static variables, you just refer to the class variable and not an instance.
void Employee::SetCompany(const Company& company) {
Employee::company = company;
}
I think it's important for you to understand the compiler's and language scoping rules. When a method (static or otherwise) has a PARAMETER that has a name "company", but the class has an accessible MEMBER (static or otherwise) that has a name "company", what are the rules for resolving the bare name "company"? What if there was no parameter named company, how can/should you reference the member?
Here's another wrinkle - what if there is a LOCAL parameter named company?
void Employee::CompareCompany(const Company &company)
{
Company company("another company");
// which company is being referenced on the LHS (left hand side)
// of the == expression below? The method parameter or the local variable?
if (company == Employee::company)
stout << "They match!"
}
Do you think this is a good idea for me to keep using the same name? They're all instances of Company, so why isn't "company" a good name for all of them???

C++ passing reference to class' private variable - compiler issue?

Is the passing by reference of a private variable in a class to be directly changed outside that class acceptable practice? Or is this something that the compiler 'should' pick up and prevent?
Example:
//-------------------------------------------
class Others
{
public:
Others() {};
void ChangeIt(string &str) { str = "Changed by Others"; }
};
//-------------------------------------------
class Locals
{
private:
string PrivateString;
public:
Locals() { PrivateString = "Set by Locals"; };
void VisitOthers() { Others o; o.ChangeIt(PrivateString); }
const string GetString() { return PrivateString; }
};
//-------------------------------------------
int main(void)
{
Locals lo;
cout << lo.GetString() << "\n";
lo.VisitOthers();
cout << lo.GetString() << "\n";
return 0;
}
Output:
Set by Locals
Changed by Others
I need to do something like this using other/different objects, private to the owner class, but changeable by others when needed. Last thing I want is for this kind of practice to come back & byte me in the future.
What is essentially worrying me, is that I would like to view the class/struct as basically a pointer to a buffer, and the member's address as offsets into this buffer, so that even if you pass the pointer-value of a member it would be useless without the base-pointer of the class/struct to which it belongs. This is what I instinctively feel should be the case, so that the above example should not even be possible.
There is nothing to prevent, you pass your private member by reference. The function you are calling isn't accessing your private member, it is changing it's own argument (that happens to be the member of some class). The code is OK, but the important thing is that the function you called doesn't keep a reference to your private member.
As the designer of the class, C++ won't prevent you to hand out reference to class private members to anyone. It may however be advisable to restrict such access to only authorized entities e.g. friends, in which case access to such private members is not really a big concern as it is 'by design'.
EDIT 2:
The mutating version of operator[] for a class also typically provides an interface for the external entities to modify the private members.
This is not good practice.
If you want other objects to modify your object, then go for
Friend classes and Friend functions
Passing private members is totally okay. You would indicate that VisitOthers() does not change your object by making it a const method. If the method was:
void VisitOthers() const {Other o; o.visit(PrivateString);}
you would get a compiler error, because you would only allowed to pass PrivateString as a const object. It is very important though that you indicate by const and your comments which methods actually change the state of your object.