views:

137

answers:

5

I understand what the typical access specifiers are, and what they mean. 'public' members are accessible anywhere, 'private' members are accessible only by the same class and friends, etc.

What I'm wondering is what, if anything, this equates to in lower-level terms. Are their any post-compilation functional differences between these beyond the high-level restrictions (what can access what) imposed by the language (c++ in this case) they're used in.

Another way to put it - if this were a perfect world where programmers always made good choices (like not accessing members that may change later and using only well defined members that should stay the same between implementations), would their be any reason to use these things?

+6  A: 

Access specifiers only exist for compilation purposes. Any memory within your program's allocation can be accessed by any part of the executable; there is no public/private concept at runtime

Michael Mrozek
That's true in general, but isn't a runtime in which that concept exists possible within the C++ specification?
Eric Mickelsen
@tehMick, no it isn't. Consider this: `class Foo { public: int } private: int a; };`. Since `getA` is defined inline, it will usually generate instructions in the calling code that access `Foo::a` directly.
Marcelo Cantos
I'm not saying that the concept would require that the access be performed differently necessarily, but, for instance, private and public members could be stored in different places or have some other more obscure access restrictions or... who knows?
Eric Mickelsen
A: 

The answer to your question could differ depending on the compiler, but in general there will be no difference. One could conceive though of an environment for which the compiled code might have different characteristics for those different accessibilities, but I'm not aware of any that exist.

Eric Mickelsen
A: 

Programmers can only make good choices when armed with the right information. Access modifiers are a way to signal to the programmer that certain things shouldn't be touched, and it has the side-benefit of enforcing correct behaviour.

There is no runtime impact. You could write a program with correct access modifiers, build it with, c++ -Dprotected=public -Dprivate=public file.cc, and it should build and produce almost exactly the same code (There are some hypothetical caveats such as data layout of classes).

Marcelo Cantos
A: 

Post-compilation, you are left with machine code (assembly) which has no notion of "public" or "private" (or of classes, members, etc). Everything is simply a memory address (whether it's code or data), and can be accessed just like any other memory address. The whole public\private distinction (as well as almost every other construct available in a high-level language) is purely for the benefit of the programmer, allowing the compiler to enforce a set of rules that are intended to make the intent of the code clearer and to help avoid potential bugs. Once compiled, your code doesn't know what language it was originally written in, much less what type of access specifiers were used.

That being said, it would be possible to rig a compiler so that it modifies the code whenever a private class member function is called in order to detect when the function is called inappropriately (add an extra parameter and set it to some expected value when the function is called from within the class; calling the function from outside of the class would provide the wrong value). The problem with this approach is what do you do now? Lock up? Do nothing and return invalid data? These types of problems are (relatively) easily detectable and correctable at compile time, so it is rare to see this sort of thing enforced at run time (outside of debugging or code profiling tools).

bta
But does that really mean that public and private access modifiers could never have any significant *affect* on that machine code?
Eric Mickelsen
@tehMick- You'd have to define "significant". The compiler might place the variable in a different section of memory, but as far as functionality goes, there is no difference. If you have the memory addresses of two members, one private and one public, you'd have no way of determining which is which in assembly (nor would there be anything that you could do to one address but not to the other). The only other thing I can think of is a compiler might be able to optimize away a private member variable, but that would be changing the original code, which is a different case entirely.
bta
Another way of looking at it is this: High-level languages compile down into machine code (assembly), thus the compiled code is limited to what is available in the assembly language of the target platform. Assembly (for all platforms I can think of) has no notion of "public" or "private", and the C++ compiler can't extend the assembly language to recognize such high-level concepts (since that would require hardware changes). Ultimately, every language feature is bound by the limitations of the underlying machine language (high-level languages are just syntactic sugar on top of assembly).
bta
+1  A: 

Michael's answer is right. Access specifiers do not directly affect the resulting code.

However, access specifiers may resolve ambiguous identifier/overload errors that would otherwise prevent compilation.

class A {
private:
    int x;
};

class B {
protected:
    int x;
};

class C : public A, public B {
public:
    int &get_x() { return x; } // only B::x is accessible, no error.
};

So they definitely serve a higher purpose than restricting the programmer.

Potatoswatter