类成员访问说明符和二进制代码
我了解典型的访问说明符是什么以及它们的含义。 “公共”成员可以在任何地方访问,“私有”成员只能由同一个班级和朋友等访问。
我想知道的是,如果有的话,这在较低级别的术语中相当于什么。它们之间的编译后功能差异是否超出了它们所使用的语言(本例中为 c++)所施加的高级限制(什么可以访问什么)。
另一种说法 - 如果这是一个完美的世界如果程序员总是做出好的选择(例如不访问以后可能会更改的成员,并且仅使用在实现之间应保持不变的定义良好的成员),那么他们有什么理由使用这些东西吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
访问说明符仅用于编译目的。程序分配的任何内存都可以由可执行文件的任何部分访问;运行时没有公共/私有概念
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'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.
So they definitely serve a higher purpose than restricting the programmer.
您的问题的答案可能会因编译器的不同而有所不同,但一般来说不会有什么区别。人们可以设想这样一种环境,其中编译的代码对于这些不同的可访问性可能具有不同的特征,但我不知道存在任何这样的环境。
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.
程序员只有在掌握了正确的信息后才能做出正确的选择。访问修饰符是向程序员发出信号的一种方式,表明某些东西不应该被触及,并且它具有强制执行正确行为的副作用。
没有运行时影响。您可以使用正确的访问修饰符编写一个程序,并使用
c++ -Dprotected=public -Dprivate=public file.cc
进行构建,并且它应该构建并生成几乎完全相同的代码(有一些假设)注意事项,例如类的数据布局)。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).编译后,您留下的机器代码(程序集)没有“公共”或“私有”(或类、成员等)的概念。一切都只是一个内存地址(无论是代码还是数据),并且可以像任何其他内存地址一样进行访问。整个公共\私有区别(以及高级语言中可用的几乎所有其他构造)纯粹是为了程序员的利益,允许编译器强制执行一组旨在实现代码意图的规则更清晰并有助于避免潜在的错误。编译后,您的代码不知道它最初是用什么语言编写的,更不用说使用什么类型的访问说明符了。
话虽如此,可以操纵编译器,以便每当调用
private
类成员函数时它都会修改代码,以便检测何时不恰当地调用该函数(添加一个额外的参数并设置当从类内部调用该函数时,它会达到某个预期值;从类外部调用该函数将提供错误的值)。这种方法的问题是你现在做什么?锁?什么都不做并返回无效数据?这些类型的问题在编译时(相对)很容易检测和纠正,因此很少看到在运行时强制实施此类问题(在调试或代码分析工具之外)。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).