c ++编译器如何知道类的位置

时间:2013-01-20 11:27:13

标签: c++ compilation

如果您定义了一个类来执行某些操作,那么您需要做的就是包含一个包含其方法原型的头文件(.h文件),但您不必包含该类文件本身(.cpp文件包含类方法的实际实现),

这是否意味着.cpp文件必须具有与其头文件相同的名称,以便编译器匹配名称以找到.cpp文件?

OR

当编译器遇到一个函数(方法)时,它会转到头文件并查看它是否有原型。然后它在其内置函数中搜索实现,如果没有找到它在当前目录中的所有.cpp文件中搜索?

或两种假设都不正确?

3 个答案:

答案 0 :(得分:4)

文件名在C ++中无关紧要。 链接器将所有部分放在一起。编译一些C ++代码时你需要知道的就是事物名称的含义。这就是声明类定义的目的:它们引入了名称,从而为编译器提供了足够的信息来生成代码:

<强> file1.cpp:

int f(int, bool);         // declaration

class Foo;                // class declaration

class Bar { int g(); };   // class definition (implies declaration)

int main()
{
    Foo * p;              // OK, Foo * is a complete type, since we know that
                          // "Foo" denotes a class

    // p->h();            // Error: We don't know what Foo actually is!

    Bar b;                // OK, we know how size and alignment for Bar

    int m = b.g();        // OK, we know what sort of function B::g() is

    int n = f(50, true);  // OK, we don't need to know what f does

    return m + n;
}

编译上述代码后,它将包含fB::g未解析符号。只要 one (且只有一个)其他翻译单元包含这些符号的定义,链接器就可以解析它们并且程序可以成功链接:

<强> file2.cpp:

int f(int n, bool b) { return b ? n * 2 : 50 - n; }

// include class definition here
int Bar::g() { return f(sizeof(Bar), sizeof(int) == sizeof(char)); }

基本规则是你可以声明一个函数或类或定义一个类 a,你可以只定义一个函数和一个类成员函数。有一个例外:如果您将类成员函数的函数声明为inline,那么只要所有定义都相同,您就可以重复定义它。

此规则的必然结果是,您可以安全地将所有函数声明和类定义放入头文件中并重复包含它,只要您只在一个转换单元中提供一次实际定义即可。 (并且inline规则允许您在类定义中包含实际的成员函数定义 - 与其声明一起定义的成员函数是隐式inline。)

答案 1 :(得分:2)

编译器只需要头文件。但是所有C ++文件都需要编译,因此链接器可以生成最终的二进制文件。

答案 2 :(得分:1)

为了生成程序,编译器需要两者。通常,从C ++到二进制的编译分两步进行,首先将每个CPP文件(也称为翻译单元)转换为目标文件(主要包含机器代码,但也包括地址表)。然后,目标文件彼此连接(链接)(需要地址表),形成最终的可执行文件。通常,在头文件中,您说“有一个带有这些参数和此返回值的函数”。在目标文件中,然后将对该函数的调用记录为对该函数的引用。最后,在链接时,此引用将使用必须由其他目标文件提供的函数的实际地址来解析。