C ++ - 转发声明 [英] C++ - Forward declaration

查看:144
本文介绍了C ++ - 转发声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在: http://www.learncpp.com/cpp-tutorial/19-header-文件/



提到以下内容:



add.cpp:

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

main.cpp:

  #include< iostream> 

int add(int x,int y); //使用函数原型的向前声明

int main()
{
using namespace std;
cout<< 3和4的和是< add(3,4)<< endl;
return 0;
}




编译器将知道编译main.cpp时添加的内容。如前所述,对于你想要使用的每个函数,写在另一个文件中的前向声明可能会很快繁琐。


转发声明?如果我们在 main() function?

解决方案

为什么在C ++中需要前向声明



编译器希望确保您没有拼写错误或传递错误的数字的函数参数。因此,它坚持在它被使用之前首先看到一个'add'(或任何其他类型,类或函数)的声明。



这只是允许编译器做一个更好的验证代码的工作,并允许它整理松散的结束,以便它可以产生一个整洁的对象文件。如果你不必转发声明的东西,编译器将产生一个目标文件,它必须包含关于所有可能的猜测的信息,关于什么是添加功能。并且链接器必须包含非常聪明的逻辑来尝试和工作出'add'你实际打算调用,当'add'函数可能生活在一个不同的目标文件中的链接器加入使用添加产生dll或exe。这可能是链接器可能得到错误的添加。说你想使用int add(int a,float b),但不小心忘了写它,但链接器发现一个已经存在的int add(int a,int b),并认为是正确的一个,而改用它。



因此,为了保持显式,避免猜测等,编译器坚持要求你先声明一切

声明和定义之间的区别



重要的是要知道声明和定义之间的区别。一个声明只是给出了足够的代码来显示什么样子,所以对于一个函数,这是返回类型,调用约定,方法名称,参数及其类型。但是方法的代码不是必需的。对于一个定义,你需要声明,然后也需要函数的代码。



前缀声明如何显着减少构建时间 / p>

您可以通过#包含已经包含函数声明的头来获取函数到当前.cpp或.h文件的声明。但是,这可能会减缓你的编译,特别是如果你#include一个.h而不是你的程序的.cpp的头文件,因为#include你编写的.h文件将结束#include所有的头文件你也写了#includes。突然,编译器#include了需要编译的页面和页面,即使你只想使用一个或两个函数。为了避免这种情况,你可以使用向前声明,只需在文件的顶部自己输入函数的声明。如果你只使用几个函数,这可以真正地使你的编译更快相比,总是#including头。对于真正大的项目,差异可能是一个小时或更多的编译时间购买到几分钟。



打破循环引用,其中两个定义都使用每个其他



此外,前瞻性声明可以帮助您打破周期。这是两个功能都尝试使用彼此。当这种情况发生(它是一个完全有效的事情要做),你可以#include一个头文件,但该头文件尝试#include你正在写的头文件....其中#includes其他头,其中包括您正在写的一个。你被困在一个鸡和蛋的情况,每个头文件试图重新包括另一个。要解决这个问题,您可以在一个文件中前缀声明所需的部分,并将#include从该文件中删除。



例如:



文件Car.h

  #include h//包括Wheel的定义,因此它可以在Car中使用。 
#include< vector>

class Car
{
std :: vector< Wheel>轮子
};

文件Wheel.h



Hmm ...这里需要Car的声明,因为Wheel有一个指向Car的指针,但是Car.h不能包含在这里,因为它会导致编译器错误。如果包括Car.h,那么将尝试包括Wheel.h将包括Car.h将包括Wheel.h,这将永远继续,所以相反,编译器引发一个错误。解决方案是转发声明Car代替:

  class Car; // forward declaration 

class Wheel
{
Car * car;
};

如果Wheel类有需要调用car方法的方法,那么这些方法可以在Wheel中定义。 cpp和Wheel.cpp现在能够包括Car.h而不导致循环。


At: http://www.learncpp.com/cpp-tutorial/19-header-files/

The following is mentioned:

add.cpp:

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

main.cpp:

#include <iostream>

int add(int x, int y); // forward declaration using function prototype

int main()
{
    using namespace std;
    cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
    return 0;
}

We’d used a forward declaration so that the compiler would know what add was when compiling main.cpp. As previously mentioned, writing forward declarations for every function you want to use that lives in another file can get tedious quickly.

Can you explain "forward declaration" further? What is the problem if we use it in the main() function?

解决方案

Why forward-declare is necessary in C++

The compiler wants to ensure you haven't made spelling mistakes or passed the wrong number of arguments to the function. So, it insists that it first sees a declaration of 'add' (or any other types, classes or functions) before it is used.

This really just allows the compiler to do a better job of validating the code, and allows it to tidy up loose ends so it can produce a neat looking object file. If you didn't have to forward declare things, the compiler would produce an object file that would have to contain information about all the possible guesses as to what the function 'add' might be. And the linker would have to contain very clever logic to try and work out which 'add' you actually intended to call, when the 'add' function may live in a different object file the linker is joining with the one that uses add to produce a dll or exe. It's possible that the linker may get the wrong add. Say you wanted to use int add(int a, float b), but accidentally forgot to write it, but the linker found an already existing int add(int a, int b) and thought that was the right one and used that instead. Your code would compile, but wouldn't be doing what you expected.

So, just to keep things explicit and avoid the guessing etc, the compiler insists you declare everything before it is used.

Difference between declaration and definition

As an aside, it's important to know the difference between a declaration and a definition. A declaration just gives enough code to show what something looks like, so for a function, this is the return type, calling convention, method name, arguments and their types. But the code for the method isn't required. For a definition, you need the declaration and then also the code for the function too.

How forward-declarations can significantly reduce build times

You can get the declaration of a function into your current .cpp or .h file by #includ'ing the header that already contains a declaration of the function. However, this can slow down your compile, especially if you #include a header into a .h instead of .cpp of your program, as everything that #includes the .h you're writing would end up #include'ing all the headers you wrote #includes for too. Suddenly, the compiler has #included pages and pages of code that it needs to compile even when you only wanted to use one or two functions. To avoid this, you can use a forward-declaration and just type the declaration of the function yourself at the top of the file. If you're only using a few functions, this can really make your compiles quicker compared to always #including the header. For really large projects, the difference could be an hour or more of compile time bought down to a few minutes.

Break cyclic references where two definitions both use each other

Additionally, forward-declarations can help you break cycles. This is where two functions both try to use each other. When this happens (and it is a perfectly valid thing to do), you may #include one header file, but that header file tries to #include the header file you're currently writing.... which then #includes the other header, which #includes the one you're writing. You're stuck in a chicken and egg situation with each header file trying to re #include the other. To solve this, you can forward-declare the parts you need in one of the files and leave the #include out of that file.

Eg:

File Car.h

#include "Wheel.h"  // Include Wheel's definition so it can be used in Car.
#include <vector>

class Car
{
    std::vector<Wheel> wheels;
};

File Wheel.h

Hmm... the declaration of Car is required here as Wheel has a pointer to a Car, but Car.h can't be included here as it would result in a compiler error. If Car.h was included, that would then try to include Wheel.h which would include Car.h which would include Wheel.h and this would go on forever, so instead the compiler raises an error. The solution is to forward declare Car instead:

class Car;     // forward declaration

class Wheel
{
    Car* car;
};

If class Wheel had methods which need to call methods of car, those methods could be defined in Wheel.cpp and Wheel.cpp is now able to include Car.h without causing a cycle.

这篇关于C ++ - 转发声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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