Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I expose private members when I return a reference from a public member function?

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.

like image 225
Mahesh Avatar asked Jan 16 '11 17:01

Mahesh


3 Answers

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.

like image 155
Billy ONeal Avatar answered Oct 20 '22 15:10

Billy ONeal


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.

like image 23
Donotalo Avatar answered Oct 20 '22 14:10

Donotalo


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 image 30
Chris Smith Avatar answered Oct 20 '22 14:10

Chris Smith