这是正确的?
不。
你需要了解函数声明和函数定义的区别,编译、链接和执行的区别,以及非虚函数和虚函数的区别。
函数声明
这是一个函数声明:void max(void);
. 它不会告诉编译器有关函数的作用的任何信息。它的作用是告诉编译器如何调用函数以及如何解释结果。当编译器在编译某个函数的主体时,称之为函数A,编译器不需要知道其他函数是做什么的。它只需要知道如何处理函数 A 调用的函数。编译器可能会生成与您的 C++ 函数调用相对应的汇编代码或某种中间语言代码。或者它可能会拒绝您的 C++ 代码,因为您的代码没有意义。
确定您的代码是否有意义是这些函数声明的另一个关键目的。这在多个函数可以具有相同名称的 C++ 中尤为重要。如果编译器不知道这些函数,它如何知道要调用半打左右的函数中的max
哪一个?当您的 C++ 代码调用某个函数时,编译器必须找到与这些函数声明之一的最佳匹配(可能涉及类型转换)。如果编译器根本找不到匹配项,或者它找到多个匹配项但无法将一个匹配项区分为最佳匹配项,则您的代码没有意义。
当编译器确实找到最佳匹配时,生成的代码将以调用该函数的未定义外部引用的形式出现。该函数所在的位置不是编译器的工作。
函数定义
那void max(void)
是一个函数声明。对应void max() {...}
的是该函数的定义。当编译器正在处理void max() {...}
它时,它不必担心其他函数调用了它。它只需要担心处理void max() {...}
。这个函数的主体变成了汇编或中间语言代码,插入到某个编译的目标文件中。编译器将这个生成代码的入口点的地址标记为这样。
编译与链接
到目前为止,我已经讨论了编译器的作用。它会生成与您的 C++ 代码相对应的低级代码块。由于这些外部引用,生成的代码还没有准备好迎接黄金时段。解决那些未定义的外部引用是链接器的工作。链接器是从多个目标文件、多个库构建可执行文件的工具。它跟踪将这些代码块放在可执行文件中的位置。那些未定义的外部引用呢?如果链接器已经将该引用放置在可执行文件中,则链接器只需填写该引用的占位符。如果链接器没有遇到该引用的定义,它会将引用和占位符放在仍然未解析的引用列表中。每次链接器向可执行文件添加一段代码时,它检查该列表以查看它是否可以修复任何那些仍未解决的引用。最后,您要么解决了所有参考文献,要么仍然有一些未完成的参考文献。后者是一个错误。前者意味着你有一个可执行文件。
执行
当你的代码运行时,这些函数调用实际上只是一些堆栈管理,它包裹在机器语言中,相当于那个邪恶的goto
语句。无需检查您的函数声明;这些甚至在代码执行时都不存在。返回?那也是一个goto
。
非虚拟与虚拟功能
我上面所说的与非虚拟功能有关。虚拟功能确实发生了运行时调度。运行时分派与检查函数声明无关。这些虚拟功能可能是另一个问题的问题。
最后一件事:
摆脱将using namespace std;
其视为类似于吸烟的习惯。这是一个坏习惯。