简体   繁体   中英

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.

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?!?!?!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM