关于编译/链接过程的参考资料有很多,但我对一个更具体的问题感兴趣:类的编译。
这个问题出现是因为通常需要先了解一些东西才能使用。例如:如果之前没有声明函数,就不能调用它。
在类中,情况并不相同。可以在成员出现之前使用它们。编译器会做什么?标准是否对先前阶段的编译有相关规定?
为了更具体,下面的例子展示了如何使用定义在其后的成员。
#include <iostream>
class EvenOdd {
public:
EvenOdd(): value(0) {}
void assignEven(unsigned v) {
if (v>0 && v%2==1) {
std::cout << "Wrong call... is odd" << std::endl;
assignOdd(v);
}
else {
std::cout << "Right..." << v << " is Even" << std::endl;
value= v;
}
}
void assignOdd(unsigned v) {
if (v>0 && v%2==0) {
std::cout << "Wrong call... is even" << std::endl;
assignEven(v);
}
else {
std::cout << "Right..." << v << " is Odd" << std::endl;
value= v;
}
}
private:
unsigned value;
};
int main()
{
EvenOdd a;
std::cout << "Do it right..." << std::endl;
a.assignEven(2);
std::cout << "doing it wrong..." << std::endl;
a.assignEven(3);
}
我们还可以添加关于内联函数的更多问题,因为它们可能在调用点之后定义,并且编译器可以解决而没有问题。我猜答案是相关的。
更新:我知道编译/链接有几个步骤。另一方面,如果编译器接受调用下面定义的函数,那么是因为编译器在某种意义上已经分析了代码。问题是在之前完成了哪种类型的先前阶段?此外......在标准的哪个部分中,我们找到与使用下面定义的成员相关的内容?
了解编译器的工作方式非常有趣,因为它必须了解下面的函数(至少是头文件)的细节,这似乎实际上对于编译很重要。甚至数据成员也必须编译,因为您必须将其类型与上面函数的上下文相关联。
它的工作方式就像重新排序代码,但与上面的示例不一致,因为两个函数成员相互调用。就像重新排序数据成员和函数头一样,编译器可能会考虑的代码。