C ++:理解头文件&标题守卫与容易添加的例子 [英] C++: Understanding Header Files & Header Guards with Easy Addition Example

查看:130
本文介绍了C ++:理解头文件&标题守卫与容易添加的例子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法控制头部和头部守卫。我已阅读其他问题和他们的答案,但我仍然无法在Visual Studio 2013中完成这项工作:

  #includestdafx.h
#include< iostream>
#includeadd.h

int _tmain(int argc,_TCHAR * argv []){$ b $ std :: cout<< 3 + 4 =<<添加(3,4)<<的std :: ENDL;
系统(暂停);
返回0;



add.cpp



  #includestdafx.h// ADDED LATER;现在正在工作(并参见下面的问题2)
#includeadd.h// ADDED LATER; NOR工作(并参见下面的问题2)
int add(int x,int y){
return x + y;



add.h



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

当我编译时,控制台窗口在屏幕上闪烁然后消失。错误列表包含:
$ b


错误1错误LNK2019:无法解析的外部符号int __cdecl
add(int,int)( ?add @@ YAHHH @ Z)引用函数
_wmain c:\ Users \Danny\documents\visual studio 2013\Projects\Addition Program\main\main.obj main

错误2错误LNK1120:1未解决
外部错误c:\ users \danny\documents\visual studio
2013 \Projects\ Addition Program \Debug\main.exe main






1。标题和标题守卫如何工作?我看到#include add.h ,它使得 main.cpp 意识到<$ c $的声明c> add(int x,int y),但它是如何找到它的定义的?






2。我的代码有什么问题?



我的代码现在正在编译。我的代码不编译的原因是因为我一直在 File> New> File ... 中添加文件到我的项目中,而不是通过源文件 Visual Studio中解决方案资源管理器头文件部分。我还需要在add.cpp文件中添加 #includestdafx.h / div>

以这种方式考虑:每个 .cpp 文件都经过预处理,然后与其他文件完全分开编译。



因此,让我们首先预处理 main.cpp ,其中包括查看以开头的所有行。 。 main.cpp 文件只有 #include 行,它们只是复制它们包含的文件的内容。我将用注释来表示 stdafx.h iostream 的内容,但我会实际上复制 add.h 中的内容:

  //目录stdafx.h 
// 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(pa使用);
返回0;
}

现在看看 add.h 已被带入 main.cpp ?事实上,这导致了更多的预处理指令,所以我们需要做他们所说的。第一个检查 ADD_H 是否尚未定义(在这个文件中),它不是这样,所以把所有东西都保留下来,直到 #endif <

  // stdafx.h的内容
// iostream的内容
#define ADD_H
int add(int x,int y);

int _tmain(int argc,_TCHAR * argv []){
std :: cout<< 3 + 4 =<<添加(3,4)<<的std :: ENDL;
系统(暂停);
返回0;
}

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

  //目录stdafx.h 
// iostream的内容
int add(int x,int y);

int _tmain(int argc,_TCHAR * argv []){
std :: cout<< 3 + 4 =<<添加(3,4)<<的std :: ENDL;
系统(暂停);
返回0;
}

现在可以编译这个文件。如果您调用像 add 这样的函数,编译器只需要能够看到该函数的声明,以便它能够成功编译。预计该函数将在某些其他翻译单元中定义。



现在让我们看看预处理 add的.cpp 。事实上, add.cpp 没有任何预处理指令,所以什么都不需要发生。通常,你会 #includeadd.h,但是如果你不这样做,你的程序仍然会被编译。所以在预处理之后,我们仍然有:

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

然后编译完成,我们现在定义了添加函数。



毕竟 .cpp 然后链接。链接器负责看到已编译的 main.cpp 使用函数 add 并查找它的定义。它在编译的 add.cpp 中找到了定义并将它们连接在一起。




然后,你可能会想知道我们为什么要包括警卫。在这个例子中,它似乎很没用。没错,在这个例子中它并没有什么用处。包括警卫在内,以防止在单个文件中包含两次相同的头文件。当你有更复杂的项目结构时,这很容易发生。但是,我们来看一个不切实际的例子,其中 main.cpp 包含 add.h 两次:

  #includestdafx.h
#include< iostream>
#includeadd.h
#includeadd.h

int _tmain(int argc,_TCHAR * argv []){
std :: cout<< 3 + 4 =<<添加(3,4)<<的std :: ENDL;
系统(暂停);
返回0;
}

预处理过程会给您:

  // stdafx.h的内容
// 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 =<<添加(3,4)<<的std :: ENDL;
系统(暂停);
返回0;

第一个 #ifndef 会被处理,它会看到 ADD_H 尚未定义,直到 #endif 的所有内容都将保留。然后定义 ADD_H

然后第二个 #ifndef 已经被处理,但是现在已经定义了 ADD_H ,所以直到 #endif 都会被丢弃。



这非常重要,因为有多个函数定义(以及许多其他的东西)会给你一个错误。


I can't get my head around headers and header guards. I've read other questions and their answers but I still can't make this work in 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

When I compile, the console window flashes on-screen then disappears. The Error List contains:

Error 1 error LNK2019: unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z) referenced in function _wmain c:\Users\Danny\documents\visual studio 2013\Projects\Addition Program\main\main.obj main

Error 2 error LNK1120: 1 unresolved externals c:\users\danny\documents\visual studio 2013\Projects\Addition Program\Debug\main.exe main


1. How do headers and header guards work? I see how by #including add.h, it makes main.cpp aware of the declaration of add(int x, int y), but then how does it find its definition?


2. What have I got wrong in my code?

My code is compiling now. The reason my code wasn't compiling was because I had been going File > New > File... to add files to my project, as opposed to adding them through the Source Files and Header Files sections of the Solution Explorer in Visual Studio. I also needed to add #include "stdafx.h to the add.cpp file.

解决方案

Think of it this way: each .cpp file is preprocessed and then compiled completely separately from the other files.

So let's first preprocess main.cpp. This involves looking at all the lines beginning with #. The file main.cpp only has #include lines, which simply copy the contents of the file they're including. I'm going to represent the contents of stdafx.h and iostream with a comment, but I'll actually copy the contents of add.h in:

// 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;
}

See now that the contents of add.h have been brought into main.cpp? And it so happens that this has brought in some more preprocessor directives, so we'll need to do what they say. The first checks if ADD_H is not defined yet (in this file), which it is not, and so leaves everything up until the #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;
}

Now the remaining preprocessor directive defines ADD_H and we're left with the final translation unit:

// 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;
}

Now this file can be compiled. If you call a function like add, the compiler only needs to be able to see the declaration of that function for it to compile successfully. It is expected that the function will be defined in some other translation unit.

So now let's look at preprocessing add.cpp. In fact, add.cpp doesn't have any preprocessing directives, so nothing needs to happen. Typically, you would #include "add.h", but your program will still compile if you don't. So after preprocessing we still have:

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

This then gets compiled and we now have a definition of the add function.

After all .cpp files have been compiled, they are then linked. The linker is responsible for seeing that the compiled main.cpp uses the function add and so looks for its definition. It finds the definition in the compiled add.cpp and links them together.


You may then wonder why we have include guards at all. It seemed to be pretty worthless in this example. That's right, in this example it didn't really have any use. Include guards are there to prevent the same header being included twice in a single file. This can easily happen when you have a more complex project structure. However, let's look at an unrealistic example where main.cpp includes add.h twice:

#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;
}

Preprocessing this gives you:

// 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;
}

The first #ifndef will be process, it will see that ADD_H is not yet defined, and everything up until the #endif will remain. This then defines ADD_H.

Then the second #ifndef is processed, but at this point ADD_H has been defined, so everything up until the #endif will be discarded.

This is very important because having multiple definitions of a function (and many other things) will give you an error.

这篇关于C ++:理解头文件&amp;标题守卫与容易添加的例子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆