C ++:了解头文件和页眉卫兵与Easy加入实施例(C++: Understanding Heade

2019-10-19 07:04发布

我不能让我的周围头和头警卫头。 我读过其他的问题进行解答,但我还是不能让在Visual Studio 2013年这一工作:

main.cpp

#include "stdafx.h"
#include <iostream>
#include "add.h"

int _tmain(int argc, _TCHAR* argv[]) {
    std::cout << "3 + 4 = " << add(3, 4) << std::endl;
    system("pause");
    return 0;
}

add.cpp

#include "stdafx.h" //ADDED LATER; NOW WORKING (AND SEE QUESTION 2 BELOW)
#include "add.h" //ADDED LATER; NOR WORKING (AND SEE QUESTION 2 BELOW)
int add(int x, int y) {
    return x + y;
}

add.h

#ifndef ADD_H
#define ADD_H
int add(int x, int y);
#endif

当我编译,屏幕上的控制台窗口闪烁然后消失。 错误列表包括:

错误1个错误LNK2019:(?@@添加@ YAHHH Z)无法解析的外部符号 “INT __cdecl添加(INT,INT)” 的功能_wmainÇ引用:\用户\丹尼\文件\的Visual Studio 2013 \项目\追加程序\主\ main.obj主

错误2错误LNK1120:1个无法解析的外部C:\用户\丹尼\文件\的Visual Studio 2013 \项目\追加程序\调试\ MAIN.EXE主


1.如何做头和头警卫工作? 我看到如何通过#包括add.h ,它使main.cpp意识到的声明add(int x, int y) ,但当时它是如何找到它的定义是什么?


2.我有什么错我的代码?

我的代码现在编译。 我的代码无法编译的原因是因为我已经打算文件>新建>文件...将文件添加到我的项目,而不是通过在Visual Studio Solution Explorer中源文件头文件部分添加。 我还需要添加#include "stdafx.h的add.cpp文件。

Answer 1:

认为它是这样的:每个.cpp文件进行预处理,然后从其他文件编译完全分开。

所以,让我们先预处理main.cpp 。 这包括寻找与开头的所有行# 。 该文件main.cpp仅有#include线,简单地复制他们包括文件的内容。 我要代表的内容stdafx.hiostream与评论,但是我会真正的内容复制的add.h在:

// Contents of stdafx.h
// Contents of iostream
#ifndef ADD_H
#define ADD_H
int add(int x, int y);
#endif

int _tmain(int argc, _TCHAR* argv[]) {
    std::cout << "3 + 4 = " << add(3, 4) << std::endl;
    system("pause");
    return 0;
}

现在的内容见add.h已纳入main.cpp ? 而恰巧这在一些预处理指令带来的,所以我们需要做的他们说什么。 如果第一个检查ADD_H尚未确定(在此文件),它是没有,所以一切都留下,直到#endif

// Contents of stdafx.h
// Contents of iostream
#define ADD_H
int add(int x, int y);

int _tmain(int argc, _TCHAR* argv[]) {
    std::cout << "3 + 4 = " << add(3, 4) << std::endl;
    system("pause");
    return 0;
}

现在剩下的预处理指令定义ADD_H ,我们只剩下最后的翻译单位

// Contents of stdafx.h
// Contents of iostream
int add(int x, int y);

int _tmain(int argc, _TCHAR* argv[]) {
    std::cout << "3 + 4 = " << add(3, 4) << std::endl;
    system("pause");
    return 0;
}

现在,这个文件可以被编译。 如果你调用像功能add ,编译器只需要能够看到,函数的声明为它编译成功。 据预计,该功能将在其他一些翻译单位来定义。

所以,现在让我们来看看预处理add.cpp 。 事实上, add.cpp没有任何预处理指令,所以没有什么需要发生。 通常情况下,你会#include "add.h" ,但如果你不这样做你的程序将仍然编译。 因此,预处理后,我们仍然有:

int add(int x, int y) {
    return x + y;
}

然后,这被编译,我们现在有一个定义add功能。

毕竟.cpp文件都被编译,然后它们联系在一起的 。 链接器是负责确保编译main.cpp使用函数add等查找它的定义。 它发现在编译的定义add.cpp并将它们链接在一起。


那么你可能想知道为什么我们有包括警卫可言。 这似乎是在这个例子中很值钱。 这是正确的,在这个例子中实际上都没有任何用处。 包括守卫在那里,以防止在一个文件被包含两次相同的标题。 当你有一个更复杂的项目结构,这可以很容易地发生。 然而,让我们来看看一个不切实际的例子,其中main.cpp包括add.h两次:

#include "stdafx.h"
#include <iostream>
#include "add.h"
#include "add.h"

int _tmain(int argc, _TCHAR* argv[]) {
    std::cout << "3 + 4 = " << add(3, 4) << std::endl;
    system("pause");
    return 0;
}

预处理这给你:

// Contents of stdafx.h
// Contents of iostream
#ifndef ADD_H
#define ADD_H
int add(int x, int y);
#endif
#ifndef ADD_H
#define ADD_H
int add(int x, int y);
#endif

int _tmain(int argc, _TCHAR* argv[]) {
    std::cout << "3 + 4 = " << add(3, 4) << std::endl;
    system("pause");
    return 0;
}

第一次#ifndef会过程中,会看到ADD_H还没有确定,一切直到#endif将保持不变。 这就定义了ADD_H

然后,第二#ifndef被处理,但在这一点ADD_H已被定义,所以一切直到#endif将被丢弃。

这是非常重要的,因为有一个功能(和许多其他的东西)的多个定义将会给你一个错误。



Answer 2:

IDE编译每个cpp文件继而产生用于该特定文件的对象文件(本机代码)。

有了这一切做它写入比特起来,形成一个可执行文件。 在IDE知道需要什么关联。

这是一个有点简单化anwser



文章来源: C++: Understanding Header Files & Header Guards with Easy Addition Example