简体   繁体   English

作为初学者理解 C++ 中的预处理器指令

[英]Understanding Preprocessor Directives in C++ as a beginner

I recently began learning C++.最近开始学习C++。 As a programmer coming from Python, I've noticed some general similarities when it comes to how certain things in C++ do the same thing over in Python.作为一名来自 Python 的程序员,我注意到 C++ 中的某些事情如何在 Python 中做同样的事情时有一些普遍的相似之处。

One question I had is understanding Preprocessor directives.我遇到的一个问题是理解预处理器指令。 I/O Stream seems to be a common one to use in beginner programs. I/O Stream 似乎是初学者程序中常用的一种。

Is #include effectively the same thing as import in Python, or is it completely different than importing "modules"? #include与 Python 中的import实际上是一样的,还是与导入“模块”完全不同?

C++ did not have modules until the latest standard (C++20). C++ 在最新标准 (C++20) 之前没有模块。 #include is not the same as import in the languages that support modules. #include与支持模块的语言中的import不同。 Instead, it is a source code - level inclusion of a "header" file.相反,它是“头”文件的源代码级包含。 Usually, the headers only contain declarations but not definitions of what you are "importing".通常,标头仅包含声明,而不包含您“导入”的内容的定义。 The definitions are contained in compiled libraries that are added by the linker.这些定义包含在 linker 添加的编译库中。

Congrats on diving in to C++, you're going to have many more questions and confusions coming from Python, especially if you use some of the newer standards (like C++11/14/17/20).恭喜您深入了解 C++,您将会有更多来自 Python 的问题和困惑,特别是如果您使用一些较新的标准(如 C++11/14/17/20)。

That aside, answering your question directly:除此之外,直接回答您的问题:

Is #include effectively the same thing as import in Python or is it completely different than importing "modules." #include是否与 Python 中的import有效相同,还是与导入“模块”完全不同。

I won't speak to C++20 modules as that functionality is not fully supported across the various compilers and that is not your question.我不会谈论 C++20 模块,因为各种编译器不完全支持该功能,这不是你的问题。 Unfortunately the answer is not a simple yes or no, it's kind of both.不幸的是,答案不是简单的是或否,两者兼而有之。

In C and C++, the #include pre-processor directive essentially does a "copy-paste" of whatever file you #include before it does the compilation stage.在 C 和 C++ 中, #include预处理器指令本质上是在编译阶段之前对您#include的任何文件进行“复制粘贴”。 This allows you to separate large chunks of code into easier to manage files and still reference the code in said file.这使您可以将大块代码分成更易于管理的文件,并且仍然可以引用所述文件中的代码。

In Python/C#/Java and various other languages, you don't #include a file you want to access the classes and functions of, you import the namespace or module you wish to reference and the JIT compiler "knows" which file that module or namespace is in, allowing you to use the functionality of the code in that file.在 Python/C#/Java 和其他各种语言中,您不需要#include一个要访问其类和函数的文件,而是import您希望引用的命名空间或模块,并且 JIT 编译器“知道”该模块的哪个文件或命名空间在,允许您使用该文件中代码的功能。

Python and C++ don't "build" the code in the same way and thus don't reference parts of the source code in the same way. Python 和 C++ 不会以相同的方式“构建”代码,因此不会以相同的方式引用源代码的一部分。

To illustrate this point more succinctly, take the following C++ code:为了更简洁地说明这一点,请使用以下 C++ 代码:

file: fun.hpp文件: fun.hpp

#define FUN_NUM 1
namespace fun
{
    int get_fun()
    {
        return FUN_NUM;
    }
}

file: main.cpp文件: main.cpp

#include <iostream>
#include "fun.hpp"

int main(int argc, char* argvp[])
{
    if (fun::get_fun() == FUN_NUM) {
        std::cout << "Fun!" << std::endl;
    }
    return FUN_NUM;
}

In the above code, when we #include "fun.hpp" , what the C++ pre-processor does before compiling is essentially "copy-and-paste" the code in iostream and fun.hpp , so what actually gets compiled is something like the following:在上面的代码中,当我们#include "fun.hpp"时,C++ 预处理器在编译之前所做的基本上是“复制和粘贴” iostreamfun.hpp中的代码,所以实际编译的内容类似于以下:

file: main.cpp文件: main.cpp

// #include <iostream> <- this is replaced with the whole std::iostream file
// not putting that here as it's huge.

// #include "fun.hpp" <- this is replaced with this:
#define FUN_NUM 1
namespace fun
{
    int get_fun()
    {
        return FUN_NUM;
    }
}

int main(int argc, char* argvp[])
{
    if (fun::get_fun() == FUN_NUM) {
        std::cout << "Fun!" << std::endl;
    }
    return FUN_NUM;
}

It is because of this "copy-paste" that you also need to have include guards, because if you did something like the following:正是由于这种“复制粘贴”,您还需要包含警卫,因为如果您执行以下操作:

file: main.cpp文件: main.cpp

#include <iostream>
#include "fun.hpp"
#include "fun.hpp"

int main(int argc, char* argvp[])
{
    if (fun::get_fun() == FUN_NUM) {
        std::cout << "Fun!" << std::endl;
    }
    return FUN_NUM;
}

This code won't compile because you'll get errors about various items being redeclared since what gets compiled is the following:此代码不会编译,因为您将收到有关重新声明的各种项目的错误,因为编译的内容如下:

file: main.cpp文件: main.cpp

// #include <iostream> <- this is replaced with the whole std::iostream file
// not putting that here as it's huge.

// #include "fun.hpp" <- this is replaced with this:
#define FUN_NUM 1
namespace fun
{
    int get_fun()
    {
        return FUN_NUM;
    }
}
// #include "fun.hpp" <- this is replaced with this:
#define FUN_NUM 1
namespace fun
{
    int get_fun()
    {
        return FUN_NUM;
    }
}

int main(int argc, char* argvp[])
{
    if (fun::get_fun() == FUN_NUM) {
        std::cout << "Fun!" << std::endl;
    }
    return FUN_NUM;
}

To protect from the double inclusion and redefinition, you can simply do something like the following:为了防止双重包含和重新定义,您可以简单地执行以下操作:

file: fun.hpp文件: fun.hpp

#if !defined(FUN_HPP)
#define FUN_HPP
#define FUN_NUM 1
namespace fun
{
    int get_fun()
    {
        return FUN_NUM;
    }
}
#endif // define FUN_HPP

So unless you pass FUN_HPP as a pre-processor define to the compiler, then FUN_HPP will not be defined until the file is #include 'd once, then any other times it's included, FUN_HPP will already be defined and thus the pre-processor will not include the code again, ridding the problem of double-definitions.因此,除非您将FUN_HPP作为预处理器定义传递给编译器,否则FUN_HPP不会被定义,直到文件被#include 'd 一次,然后任何其他时间它被包含在内, FUN_HPP将已经被定义,因此预处理器将不再包含代码,消除了双重定义的问题。

So where your question is concerned, the #include directive in C++ is somewhat like the import directive in Python, but mostly to the effect that they both allow the file you are putting that directive in, to access code more directly from that import or #include .因此,就您的问题而言,C++ 中的#include指令有点像#include中的import指令,但主要是它们都允许您放入该指令的文件,以便更直接地从该import#include .

I hope that can add a little clarity.我希望这可以增加一点清晰度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM