在实现(.cpp)文件中不包括相应的头文件(.h)仍可以编译吗?

1992年

我今天写了一个简单的示例,只是想看看它是否可以编译,当我发现它可以编译时,我实际上感到非常惊讶!

这是示例:

你好

#ifndef HELLO_H
#define HELLO_H

// Function prototype
void say_hello();

#endif

你好

注意:这不包括“ hello.h”,就像在我永远的历史中见过的每个C ++示例一样!

// #include "hello.h" <-- Commented out. The corresponding header is NOT included.

#include <iostream>

void say_hello() {
    std::cout << "Hello!" << std::endl;
}

main.cpp

#include "hello.h"

int main() {
    say_hello();
}

然后,我将“ hello.cpp”编译为静态库,如下所示:

g++ -c hello.cpp
ar -rvs libhello.a hello.o

然后,我编译了“主”应用程序并将其链接到库

g++ -o main main.cpp -L. -lhello

并运行它,它执行得很好!

./main

你好!


当我感到惊讶的时候...我确实理解为什么这样做。这是因为“ hello.cpp”中的函数未声明为静态,因此具有外部链接并且可以从外部看到。将其设置为静态将由于未定义引用而导致链接失败。

因此,这里有一个问题……如果这行得通,那么为什么每个地方的人总是在“ .cpp”实现文件中包括“ .h”头文件和函数声明。显然,如果仅定义自由函数,则没有必要,并且如果不包含头文件,一切都会很好。

那么为什么我们总是包含它呢?-是否只是对链接器的工作原理普遍缺乏了解?还是还有更多?

马丁·邦纳(Martin Bonner)支持莫妮卡(Monica)

让我们更改您的hello.cpp

// #include "hello.h" <-- Commented out. The corresponding header is NOT included.

#include <iostream>

int say_hello() {
    std::cout << "Hello!" << std::endl;
    return 0;
}

这将与以前的版本一样编译。它也可能会链接-但不正确。返回类型错误。

这是未定义的行为,但是在许多常见的实现中,您将不使用它,因为您不使用返回值,并且通常在寄存器中将其返回。但是,不必一定如此-您在运行时可能会遇到非常奇怪的错误。特别是如果差异稍微复杂一些(如double调用者期望时返回int-通常会在不同的寄存器中返回)。

另一方面,如果您写了:

#include "hello.h"

#include <iostream>

int say_hello() {
    std::cout << "Hello!" << std::endl;
    return 0;
}

然后,头文件中的声明将与CPP文件中的定义不匹配-并且您将获得一个不错的,易于理解的编译器错误消息。

实际上,这是一个好主意,如果您没有外部函数的声明,GCC会抱怨(如果您在命令行中使用-wall -werror,它将停止您的构建。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

.cpp文件中可以包含(不包括)什么?

在C ++中包括头文件(类定义和方法实现)

您可以在一个库中实现多个头文件吗?

C++,Clang:#包括与 cpp 关联的头文件不编译

为什么我可以在头文件中实现类的成员函数?

为什么要包括头文件而不是实现?

在头文件或实现中包含 GTK

头文件中的C函数实现

用头文件编译不同的.cpp文件

如何在头文件(.h)中使不可变的只读属性成为实现(.m)中的可变读写属性

为什么头文件有单独的实现文件?(我的教授正确吗?)

凿子可以将printf实现到文件吗?

头文件中定义了多个结构-我应该将它们移到单独的h和cpp文件中吗

为什么C ++头文件不需要包含实现文件(.cpp)?

一个类的实现分为头文件和.cpp文件

在Unix / Linux(Ubuntu)中编译头文件和两个.cpp文件

C++ 编译不同的 .cpp 文件,将它们包含在头文件中

在Visual Studio中为函数定义和头文件编译单独的.cpp文件

可以使用不同的实现文件来实现多态吗?

Cmake:如何在Android Studio中包括.h文件以及从Android代码调用头文件的方法

包括.cpp文件和.h文件(在cpp中具有相同内容)的区别?

从头文件中隐藏指针成员实现

头文件中模板类实现的模板成员

为什么只能在头文件中实现模板?

C语言编程。如果需要在头文件(.h)中引用其实例,如何在.c中隐藏该结构的实现

如何相应地构建代码(在头文件和源文件中),以免出现编译器和链接器错误?

为什么在包含标准库中的头文件时不需要向编译器传递相应的源文件?

在头文件中实现小功能,包括在同一个项目中的两个不同文件中

如何实现给定头文件的接口?