问题描述
我是一个适度的有经验的Java / C#程序员,我最近开始学习C ++。问题是,我无法理解如何构建各种头文件和代码文件。这似乎主要是由于我缺乏理解编译器是如何联系在一起的一切。我试着读一些教科书,但我的预想,被我Java和C#的知识严重着色。例如,我有一个困难时期即将交手与方法等可以在一个命名空间,而不是只在一个类定义来定义的事实。
我已经找到了很多C ++的 - >的Java / C#教程,但几乎没有什么走另一条路。是否有良好的资源,在那里为缓解在Java / C# - > C ++的过渡,尤其是对于理解编译过程
我如果谷歌的C ++教程想,你就可以找到的东西。你也可以尝试学习汇编语言(或者至少得到一个简要介绍,以事物实际上是如何在微处理器发生),C和C ++均相当接近他们做事方式的硬件。这是他们的速度和力量从何而来,但它是在一些更好的抽象Java提供的价格。
我可以尝试回答你上面问的具体问题,但我不知道我有多好会做。
一个关键理解头文件和cpp文件之间的关系是理解的想法翻译单元。 Java类文件可以被认为是一个翻译单元,因为它是被编译成二进制形式的基本单位。在C ++中,几乎每一个CPP文件是一个翻译单元(也有例外,如果你正在做怪异的东西)。
一个头文件可以包含在多个翻译单位(必须包含到处使用无论是在头文件中定义)。 #include指令真的只是做了文本替换 - 包含文件的内容逐字插入其中#include指令。通常要在头文件中定义你的类接口,并在cpp文件的执行情况。这是因为你不想成为暴露你的实施细则,其他翻译单元可以包含头。在C ++中,应有尽有,包括类,并不是真正的丰富的对象,只是内存块,编译器在编译相同的标题信息到每个翻译单元分配的含义......,编译器保证所有的翻译单元有什么样的内存块代表相同的理解。由于缺乏编译时间后,数据丰富的,像反射是不可能的。
在C ++的编译过程是连接第二个步骤,这是在连接器通吃编译后的翻译单元,并查找符号(通常是函数调用,而且变量)在翻译单元中使用,但没有定义。然后它寻找另一个翻译单元,其定义了符号和链接在一起,以使特定功能的所有呼叫被定向到翻译单元定义它
在类方法的情况下,它们必须通过一个类的实例,这是在幕后只是一个指向一块存储器调用。当编译器看到这些类型的方法调用,它输出调用一个函数的代码,含蓄地传递指针,被称为这个
的指针,该函数的第一个参数。你可以有不属于类功能(而不是方法,就像你说的,因为一个方法是正确的类的成员函数,因此没有一个类可以不存在),因为链接器没有一类的概念。它会看到调用函数的翻译单元定义的函数,另一个和领带在一起。
这结束了很多的时间比我预期的,当然过于简单,但它是精确到我所知,并提供的细节水平...希望它可以帮助一些。至少它应该给你一些谷歌上搜索的一个起点。
I'm a moderately experienced Java / C# programmer, and I've recently started learning C++. The problem is, I'm having trouble understanding how to structure the various header and code files. This seems mostly due to my lack of understanding as to how the compiler links everything together. I've tried reading some textbooks, but my preconceptions are heavily colored by my Java and C# knowledge. For example, I'm having a hard time coming to grips with the fact that methods and the like can be defined in a namespace rather than only in a class definition.
I've found plenty of C++ -> Java/C# guides, but practically nothing to go the other way. Are there any good resources out there for easing the Java/C# -> C++ transition, particularly with respect to understanding the compiling process?
The C++ FAQ is an excellent resource about all the idiosyncrasies of C++, but it's probably a little more advanced than you're looking for -- most of the questions (not just the answers) are mysteries even to fairly experienced C++ developers.
I think if you google for C++ tutorials, you'll be able to find something. You may also want to try learning assembly language (or at least getting a quick introduction as to how things actually happen in a microprocessor), as both C and C++ are quite close to the hardware in the way they do things. This is where their speed and power comes from, but it comes at the price of some of the nicer abstractions Java offers.
I can try to answer your specific questions asked above, but I don't know how well I'll do.
One of the keys to understanding the relationship between header files and cpp files is understanding the idea of a "translation unit". A Java class file can be considered a translation unit as it is the basic unit that is compiled into a binary form. In C++, pretty much every cpp file is a translation unit (there are exceptions if you're doing weird stuff).
A header file may be included in multiple translation units (and must be included everywhere that uses whatever is defined in the header). The #include directive literally just does a text substitution -- the contents of the included file are inserted verbatim where the #include directive is. You normally want your class interface to be defined in the header file, and the implementation in the cpp file. This is because you don't want to be exposing your implementation details to other translation units that may include the header. In C++, everything, including classes, aren't really rich objects, but just chunks of memory that the compiler assigns meaning to... by compiling the same header information into each translation unit, the compiler guarantees that all the translation units have the same understanding of what a chunk of memory represents. Because of the lack of rich data after compile time, things like reflection are impossible.
The second step in the C++ build process is linking, which is where the linker takes all the compiled translation units and looks for symbols (usually function calls, but also variables) used in a translation unit but not defined there. It then looks for another translation unit that defines that symbol and "links" them together, so that all calls to a particular function are directed to the translation unit that defines it.
In the case of class methods, they must be called through a class instance, which is behind the scenes just a pointer to a piece of memory. When the compiler sees these types of method calls, it outputs code that calls a function, implicitly passing the pointer, known as the this
pointer, to the function as the first argument. You can have functions that do not belong to classes (not methods, as you said, because a method is properly a member function of a class and thus cannot exist without a class) because the linker has no concept of a class. It will see a translation unit that defines a function and another that calls a function and tie them together.
That ended up being a lot longer than I expected, and of course is an oversimplification, but it is accurate to the best of my knowledge and the level of detail provided... hope it helps some. At least it should give you a starting point for some googling.
这篇关于从Java / C#的角度了解C ++编译器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!