c++scopeglobal-variablesdifferencepublic-members

C++ public variable scope confusion


If you declare a public variable in a class, then you can modify that variable from any function that is also a member of that class.

If you declare a variable within a function, then its scope doesn't exceed the bounds of the function.

So is a public class variable essentially a global variable that can be accessed and changed by any member of the class?

If that's the case, what's the difference between a global and public variable?


Solution

  • If you declare a public variable in a class, then you can modify that variable from any function that is also a member of that class.

    Not exactly: the same also applies to private and protected variables. That is, if a class has 3 variables, one of them being public, one protected and one private, the functions that are members of that class can't only modify the public one; on the contrary, they can modify all 3. Being a member of the same class gives you the highest permissions. The difference between these 3 access modifiers can be seen when trying to manipulate those variables from outside that class: public variables are reachable from anywhere, protected variables are reachable from the same class and from classes derived from it (if there are any), and private ones are reachable only from other members of the same class.

    If you declare a variable within a function, then its scope doesn't exceed the bounds of the function.

    Yes, and the same actually applies to any block: if you declare a variable inside a for loop, its scope will be the loop. Functions are just one kind of block.

    So is a public class variable essentially a global variable that can be accessed and changed by any member of the class?

    No, as I said above a public class variable can be accessed by members of any class, and even from something that doesn't belong to any class at all: that's exactly the meaning of "public".

    If that's the case, what's the difference between a global and public variable?

    As CoryKramer said in his answer, a class member lives inside an object, and objects are independent of each other, so if you create 10 objects of the same class, all 10 will have their own copy of that variable. static class members are an exception, because they are shared by all the objects of the class, and actually don't even need a single object to be present (are you familiar with the concept of Singleton? Without static members it wouldn't work).

    A practical difference: let's say you want to store the name of a file in a place that is easily accessible from all your functions. A global will do. A public member of a class, instead, requires you to create an object of that class first, and then that object must be in scope! If you create the object inside main() and then you want to read that variable from a function called write_results_to_file(), so that you know which file to write to, you must take care about passing the object to that function, otherwise the object will be out of scope and the public member will be unreachable, despite being public.

    So global variable come more handy, as they require less work. This is exactly the reason that people like using them, but please note that this kind of laziness brings to bad code: if you use global variables, writing the code is easier, but then it's harder to understand how each function works. Ideally a function only requires its arguments, and then it can be run and produce a result. In C++ usually you can see the arguments of a function by looking at its declaration in the .hh file. But if the function accesses a global variable, we could say that the function uses a "hidden" argument, where "hidden" means that it isn't displayed in its declaration. As soon as a program grows to a non-trivial size, this actually makes things harder, because it's difficult to understand the consequences of changes. For example, if the program modifies a global variable, all the functions that use that variable will be affected, but in some cases it won't be obvious at all, and this will lead to subtle bugs that are hard to find. To make another example, testing a function can become a lot harder: if you write some test cases, you would expect that whenever you run them you get the same result, as long as the arguments you pass are the same. Instead, the result will depend on the arguments (which is clear) and also on the value of the global variables (which isn't obvious).

    That's why global variables are frowned upon: because they make it easy and fast to write code, but hard and slow to understand it and maintain it (to add new features or to fix bugs). Using them isn't forbidden, but you should do it carefully and sparingly.