前置声明的目的是什么?
例如,在下面的示例中,通过在定义类之前声明该类可以获得什么额外的好处?
class test;
class test
{
.....
};
In the following example, for instance, what additional benefit could be gained by declaring the class before defining it?
class test;
class test
{
.....
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
C++(与 C 一样)被设计为可由单遍编译器实现。如果编译器需要在实际定义类之前知道符号引用该类,则需要前向引用。典型的例子是两个类需要包含指向彼此的指针。即,
如果没有对 B 的前向引用,编译器将无法成功解析 A 的定义,并且您无法通过将 B 的定义放在 A 之前来解决问题。
在像 C# 这样需要两遍编译器的语言中,您不需要前向引用,
因为编译器的第一遍只是简单地获取所有符号定义。当编译器进行第二遍时,它可以说“我知道 B 是一个类,因为我在第一遍中看到了定义”。
C++ (like C) was designed to be implementable by a single-pass compiler. Forward references are necessary in cases where the compiler needs to know that a symbol refers to a class before the class is actually defined. The classic example of this is when two classes need to contain pointers to each other. i.e.
Without the forward reference to B, the compiler could not successfully parse the definition for A and you can't fix the problem by putting the definition of B before A.
In a language like C#, which needs a two-pass compiler, you don't need forward references
because the compiler's first pass simply picks up all symbol definitions. When the compiler makes its second pass, it can say "I know B is a class because I saw the definition on my first pass".
如果访问该类的成员/方法或者需要知道其大小,则编译器需要该类的定义。在其他情况下,前向声明就足够了。这可以节省您的编译时间。
示例:
对于此类,您需要 B 的定义(需要大小)并且仅需要 C 的声明(指针具有固定大小)。您只需要包含 B 的标头,而不是 C 的标头。C 的前向声明就足够了。
ah:
c 的前向声明(而不是包含 ch,这也是可能的)可以节省您在包含 ah 时解析 ch 的时间。跨大型项目,这可能会节省大量编译时间。
另一个好处是,在这种情况下,ch 中的更改不会触发 a 的重新编译。我不知道如果您包含 ch 而不是向前声明它,编译器是否会识别这一点。
要了解更多信息,请尝试了解 pimpl-idiom(只需 google 即可。您会得到很多结果)。
当然 - 在 a.cpp 中,如果您实际上使用指向 c 的指针执行某些操作(例如 m_ptrC->Add()),则需要包含 ch 但 a.cpp 仅在读取头文件的地方读取一次 n对于大型项目中经常使用的类,使用大 n 的次数。
前向声明还允许循环依赖。
示例:
请记住 - 您不能使用任何有关尺寸和尺寸的信息。方法(如果您使用前向声明)。两个类相互包含时也是这种情况(但其中一个类不需要前向引用)。我个人认为循环引用是不好的风格,如果可能的话应该避免它们。
有关更多信息:C++ 常见问题解答
感谢您对循环依赖项的评论,我只是忘记了它们。
The compiler needs the definition of a class if member/methods of that class are accessed or if the size needs to be known. In other cases, a forward declaration is sufficient. This saves you compile time.
Example:
For this class, you need the definition of B (size needed) and only the declaration of C (pointers have fixed size). You only need to include the header of B, not the one of C. A forward declaration of C is sufficient.
a.h:
The forward declaration of c (instead of including c.h which is also possible) saves you parsing c.h whenever you include a.h. Across a large project, this may save a lot of compile time.
Another benefit is, that changes in c.h do not trigger a recompile for a in this case. I do not know if compiler recognize this if you include c.h instead of forward declaring it.
For more information, try understanding the pimpl-idiom (just google for it. you'll get lots of hits).
Of course - in a.cpp if you actually do something with the pointer to c (e.g. m_ptrC->Add()), you'll need to include c.h. But a.cpp is read only once where the header file is read n times with large n for classes that are used very often in large projects.
Forward declaration also allows for circular dependencies.
Example:
Just remember - you can't use any information about size & methods if you use forward declarations. This is also the case with 2 classes including each other (one class does not need the forward reference though). I personally think circular references are bad style and you should avoid them if possible.
For additional information: C++ FAQ
Thank you for the comment about the circular dependencies, I simply forgot them.
首先,声明该类,然后定义该类。
声明:它只是告诉编译器:好的,这里有一些东西(方法,类等),可以通过给定的名称使用。它只是将给定名称绑定到某些东西。
定义:它告诉编译器:好的,这是方法、类等实际执行的操作(以及如何执行)。如果定义了某些内容,则会导致编译器实际为其分配空间。
您可以查看此处。
First, the class is declared, then it is defined.
Declaration: It just tells the compiler: Ok, here's something (method, class, etc.), that can be used by the given name. It just binds the given name to something.
Definition: It tells the compiler: Ok, here's what (and how) the methods, classes, etc. actually do their stuff. If something is defined, then the compiler is caused to actually allocate space for it.
You might have a look at here.
第一行是所谓的前向声明。它将类的名称带入当前名称空间,而不实际定义它。
The first line is what's called a forward declaration. It brings the name of the class into the current namespace without actually defining it.
嗯,问题不是很清楚。
但是,提供的代码声明了一个类
test
并在下面定义了它,省略了实际的成员 (...)。Ehm, the question is not very clear.
However, the code supplied declares a class
test
and defines it below, omitting the actual members (...).简单的答案是,当您使用第一种形式时,您可以保存对类的指针或引用,而不需要完整的实现。当两个类紧密交互并且它们的实现或定义难以分离时,这非常有用。
The simple answer is that when you use the first form, you can then hold pointers or references to a class without needing the full implementation. This can be very useful for when two classes tightly interact and their implementations or definitions are hard to separate.