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.
Related
A. How useful/cumbersome is the following trick of using the same function for getter as well as setter, by returning a reference?
B. How good is the practice of adding const to the end of function declarations in case of getters and setters?
#include <iostream>
class A
{
int varReadWrite_;
int varReadOnly_;
int varRestricted_;
public:
A() : varReadOnly_(25) {}
virtual ~A() {}
int& varReadWrite() { return varReadWrite_; }
int varReadOnly() { return varReadOnly_; }
int varRestricted() { return varRestricted_; }
void setVarRestricted(int i); //throwable
};
int main(int argc, char *argv[])
{
A a;
a.varReadWrite() = 45;
std::cout << a.varReadOnly() << a.varReadWrite() << std::endl;
return 0;
}
The reasons, why I chose this design was:
ease of access of explicitly read-only or explicitly writable variables.
the restricted (I dont know what else to call them), the variables, that require sanitization and filtering before being assigned -- these variables might require an explicit setter.
Using boost fusion map is also an interesting possibility as shown here
Update
Const Reference Members are interesting for read-only access to variables, e.g.
class A {
int mA;
public:
int& a;
A(int a_ = 0) : mA(a_), a(mA) {}
};
Practically this comes with the extra effort to code the copy and move constructors, which is an acceptable compromise for me.
Cpp Reference Copy Construtor says
The implicitly-declared or defaulted copy constructor for class T is defined as deleted if... T has non-static data members that cannot be copied (have deleted, inaccessible, or ambiguous copy constructors);
A. How useful/cumbersome is the following trick of using the same function for getter as well as setter, by returning a reference?
Returning a reference to your internal members in general is not recommended since this way you give an easy access to others so they could change your object internal state without using any method provided by the object's class API. Thus, it will be very difficult to track this kind of changes in the code. In general changes in the internal state of an object should only be possible through methods that belongs to the class API.
B. How good is the practice of adding const to the end of function declarations in case of getters and setters?
if you refer to adding const for methods like:
void PrintState() const
Then in general this doesn't make sense for setters. Const in this case means This method doesn't change the object state. So it's a commitment that you give to the caller to say: I will not change the object state by this call. In general it's very good practice since it helps you during the design to think about your methods and see which one is really modifying the object state or not. Additionally, it's a defensive programming since
it's recursive: if you pass this object to some method by reference (through a pointer or reference) he can't call const methods unless this method is marked as const also. So this prevents from changing the object state by error.
Accessors (a.k.a getters and setters) are as good/cumbersome as having public member variables, as you've just violated encapsulation and lied yourself. Mixing them in a single function is even worse, as the caller may hold the returned reference, opening the hole for even more subtle bugs than described in the link above.
Secondly, adding const to a member function declaration will protect you from setters, but not from getters. Anyway, plan your designs better off :).
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.
I have a lib.h, lib.cpp and test.cpp. I would like to ask what is better?
lib.h
class c
{
std::string name;
}*cc;
lib.cpp
{
std::cout << "the name is:" << name << std:: endl;
}
test.cpp
main()
{
c tst;
tst.name="diana";
}
What should I use? std::string name or std::string *name? How can i work with &name, how will my code change and which one of these 2 methods is the best one?
First, I hardly believe your code will compile while in your main you try to get access to private data member name.
About &. It is really hard to define where to start. In short std::string &name is called reference to object of type std::string. Reference is somehow an alias to some other object. The main feature is, that you always have to initialize refence to object while creating and you can't reinitialize reference to point to another object. More about this feature you can read in C++ FAQ
EDIT
Generally you can declare public, protected and private members of your class in with arbitrary ordering:
class MyClass {
//here goes private members when working with class
//and public when working with structs
public:
//here goes public members
protected:
//here goes protected
private:
//here goes private
public:
//here goes public again
};
Ordering of members declaration is actually code policy question. For example, google style guide recommends to put all public members before private.
About hiding function members (not necessary private). You actually can't hide function member declaration, but there are several ways to "hide" implementation, but I am not sure that it's the definition of hiding you are talking about. But you can check PImpl idiom. This requires understanding of pointers so I advice you to start with them first.
Small code sample for working with pointer to string:
#include <iostream>
#include <string>
class MyClass {
public:
std::string *pstr;
};
int main() {
std::string str("test");
MyClass myObj;
myObj.pstr = &str;
std::cout << myObj.pstr->c_str() << std::endl;
}
std::string & name; is a reference. You'll need to initialize it in the constructor, so it actually refers to something. What it refers to must exist as long as your c instance exists. It's not the right solution for this.
std::string name; is an actual variable, use this.
std::string &name is "only" a reference to a string (a bit like a pointer). Because the name definitely belongs to the class c, I think it would make sense to have an instance there.
References are put to good use when passing instances around (to avoid copying).
const std::string&
is reference to a std::string, it is very important to understand the implications of that with respect to the lifetime of variables. Once the referenced variable goes away, the reference is no longer valid, and this is a very common way to f*ck up for beginning C++ programmers.
YMMV, Pick up a good tutorial first, and meanwhile, don't use references unless you know why and what you're doing
Good luck
I'd use: string name; because string* name is just a pointer that needs to be given a value, and then I'd have to think of a way to clean it up later all by myself, and string& name, would be just a name that again has to be initialized.
In the code snippet, I am able to access the private member variable outside the class scope. Though this should never be done, why is it allowed in this case? Is it a bad practice to receive a returned private variable by reference ?
#include <iostream>
#include <cstdlib>
class foo
{
int x;
public:
foo(int a):x(a){}
int methodOne() { return x; }
int& methodTwo() { return x; }
};
int main()
{
foo obj(10);
int& x = obj.methodTwo();
x = 20; // With this statement, modifying the state of obj::x
std::cout << obj.methodOne();
getchar();
return 0;
}
And regarding this method, what does the return type convey ? And also when should I have return type of this kind ?
int& methodTwo() { return x; }
PS: I am sorry if the subject line is vague. Can someone change it to the content relevant here. Thanks.
private does not mean "this memory may only be modified by member functions" -- it means "direct attempts to access this variable will result in a compile error". When you expose a reference to the object, you have effectively exposed the object.
Is it a bad practice to receive a returned private variable by reference ?
No, it depends on what you want. Things like std::vector<t>::operator[] would be quite difficult to implement if they couldn't return a non-const reference :) If you want to return a reference and don't want clients to be able to modify it, simply make it a const reference.
Returning private members as reference is perfectly valid and the programmer who writes a class is responsible to carefully choose if this should be allowed. This link gives an example when this can be done.
This code:
int& methodTwo() { return x; }
Means that the function returns a reference to an integer. Just like when passing a value by reference to a function, if the return value of methodTwo gets changed, so does the value that methodTwo returned. In this case, class field x.
In the code you have written, this means that you are letting the private variable x escape its scope (a class field) and be passed around in the outside world. This certainly is a bad practice (because x can be changed in ways that may break class foo, but it is certainly allowable.
Remember public/private/protected are compile-time only. Once your application gets compiled, private fields sit next to public fields and there is no protection against modification. The same is true for managed languages like C# and Java.
You should generally avoid returning references because it makes it crazy-hard to understand when constructors/destructors get called. However, returning a reference can be faster. If your method returned a struct type that was HUGE, returning a const reference to that same struct type should only take four-to-eight-bytes (a pointer to that object). However, there are better ways to optimize for this sort of thing.
Like Donotalo said, it is perfectly valid. The idea of having private members is to disallow other classes/functions to access the private member of the class without your permission. If you are happy to make a function to allow other classes/functions to access your private members, the compiler has nothing against that really :-)
Usually, it is useful to have a private member and have a get function to allow other classes/functions to get the value of the function, but only the class will be able to change it.
I am able to access the private member variable outside the class scope
If you are referring to the x in main() then that is different from the x declared in class foo. If you try to access the obj.x then the compiler will definitely complain.
Is it a bad practice to receive a returned private variable by reference ?
There is nothing wrong in "receiving" the reference to a private member. But giving out the reference to a private member makes declaring it private useless. By declaring a variable to be a private member you restrict the access to that member only to the class' methods.
regarding this method, what does the return type convey ? And also when should I have return type of this kind ?
Not sure as to which method you are referring to?!?!?!
I understand that one benefit of having static member functions is not having to initialize a class to use them. It seems to me that another advantage of them might be not having direct access to the class's not-static stuff.
For example a common practice is if you know that a function will have arguments that are not to be changed, to simply mark these constant. e.g.:
bool My_Class::do_stuff(const int not_to_be_changed_1,
std::vector<int> const * const not_to_be_changed_2)
{
//I can't change my int var, my vector pointer, or the ints inside it.
}
So is it valid to use static member functions to limit access. For example, lets say you have a function
void My_Class::print_error(const unsigned int error_no) {
switch (error_no) {
case 1:
std::cout << "Bad read on..." << std::endl;
break;
//...
default:
break;
}
}
Well here we're not going to be accessing any member variables of the class. So if I changed the function to:
static void My_Class::print_error(const unsigned int error_no) {
switch (error_no) {
case 1:
std::cout << "Bad read on..." << std::endl;
break;
//...
default:
break;
}
}
I'd now get an error, if I inadvertently tried to access one of my private var, etc. (unless I pass myself an instance of my class, which would be purposeful ^_^ !)
Is this a valid technique, similar to proactively making args that should not be changed constants?
What downsides might it have in terms of efficiency or use?
My chief reason for asking is that most of the "static" tutorials I read made no mention of using it in this way, so I was wondering if there was a good reason why not to, considering it seems like a useful tool.
Edit 1: A further logical justification of this use:
I have a function print_error,as outlined above. I could use a namespace:
namespace MY_SPACE {
static void print_error(...) {
...
}
class My_Class {
....
void a(void)
}
}
But this is a pain, because I now have to lengthen ALL of my var declarations, i.e.
MY_SPACE::My_Class class_1;
all to remove a function from my class, that essentially is a member of my class.
Of course there's multiple levels of access control for functions:
//can't change pointer to list directly
void My_Class::print_error(std::vector<int> const * error_code_list) {...}
//can't change pointer to list or list members directly
void My_Class::print_error(std::vector<int> const * const error_code_list) {...}
//can't change pointer to list or list members directly, access
//non-const member vars/functions
void My_Class::print_error(std::vector<int> const * const error_code_list) const {...}
//can't change pointer to list or list members directly, access
//non-static member vars/functions
static void My_Class::print_error(std::vector<int> const * const error_code_list) {...}
//can't change pointer to list or list members directly, access
//member vars/functions that are not BOTH static and const
static void My_Class::print_error(std::vector<int> const * const error_code_list) const {...}
Sure this is a bit atypical, but to lessening degrees so are using const functions and const variables. I've seen lots of examples where people could have used a const function, but didn't. Yet some people think its a good idea. I know a lot of beginning c++ programmers who wouldn't understand the implications of a const function or a static one. Likewise a lot would understand both.
So why are some people so adamantly against using this as an access control mechanism if the language/spec provides for it to be used as such, just as it does with const functions, etc.?
Any member function should have access to the other members of the object. Why are you trying to protect yourself from yourself?
Static members are generally used sparingly, factory methods for example. You'll be creating a situation that makes the next person to work with your code go "WTF???"
Don't do this. Using static as an access-control mechanism is a barbaric abomination.
One reason not to do this is because it's odd. Maintenance programmers will have a hard time understanding your code because it's so odd. Maintainable code is good code. Everybody gets const methods. Nobody gets static-as-const. The best documentation for your code is the code itself. Self-documenting code is a goal you should aspire to. Not so that you don't have to write comments, but so that they won't have to read them. Because you know they're not going to anyway.
Another reason not to do this is because you never know what the future will bring. Your print_error method above does not need to access the class' state -- now. But I can see how it one day might need to. Suppose your class is a wrapper around a UDP socket. Sometime in the middle of the session, the other end slams the door. You want to know why. The last messages you sent or received might hold a clue. Shouldn't you dump it? You need state for that.
A false reason to do this is because it provides member access control. Yes it does this, but there are already mechanisms for this. Suppose you're writing a function that you want to be sure doesn't change the state of the object. For instance, print_error shouldn't change any of the object's state. So make the method const:
class MyClass
{
public:
void print_error(const unsigned int error_no) const;
};
...
void MyClass::print_error(const unsigned int error_no) const
{
// do stuff
}
print_error is a const method, meaning effectively that the this pointer is const. You can't change any non-mutable members, and you can't call any non-const methods. Isn't this really what you want?
Static member functions should be used when they are relevant to the class but do not operate on an instance of the class.
Examples include a class of utility methods, all of which are static because you never need an actual instance of the utility class itself.
Another example is a class that uses static helper functions, and those functions are useful enough for other functions outside the class.
It is certainly fair to say that global scope functions, static member functions, and friend functions aren't quite orthogonal to one another. To a certain extent, this is largely because they are intended to have somewhat different semantic meaning to the programmer, even though they produce similar output.
In particular, the only difference between a static member method and a friend function is that the namespaces are different, the static member has a namespace of ::className::methodName and the friend function is just ::friendFunctionName. They both operate in the same way.
Well, actually there is one other difference, static methods can be accessed via pointer indirection, which can be useful in the case of polymorphic classes.
So the question is, does the function belong as "part" of the class? if so, use a static method. if not, put the method in the global scope, and make it a friend if it might need access to the private member variables (or don't if it doesn't)