简体   繁体   English

C ++转发声明一个类?

[英]C++ Forward Declaring a class?

In a .h if I have: 在.h中,如果我有:

#pragma once

#include <xxxx.h>
#include "yyyy.h"

class AAAAAA;
class BBBBBB;

class ZZZZZZ
{
     public:

     // etc
 };

using class AAAAAA; 使用AAAAAA类; is forward declaring a class right? 向前宣布一个阶级权利吗?

Why would one do this? 为什么要这样做?

Is it needed? 需要吗?

What are the benefits? 有什么好处? Drawbacks? 缺点?

Why would one do this? 为什么要这样做?

Because the compiler only knows names that have been declared. 因为编译器仅知道已声明的名称。 So if you want to use a class, you have to declare it. 因此,如果要使用类,则必须对其进行声明。 But if its definition depends on its user, a forward declaration can suffice if the user doesn't depend on the definitin of the class in turn, but just on its declaration (= name). 但是,如果其定义依赖于其用户,则前向声明就可以满足,如果用户不依次依赖于类的definitin,而仅依赖于其声明(=名称)。

In particular, if the user just needs a pointer or referece, it doesn't depend on the definition. 特别是,如果用户只需要一个指针或引用,则它不依赖于定义。 But in the cases listed (which do not claim to be exclusive, since it's a standard non-normative excerpt), the user depends on the definition of class T if 但是在列出的情况下(由于它是标准的非规范摘录,因此并不声称是排他性的),如果

  • an object of type T is defined (3.1), or 定义了类型为T的对象(3.1),或
  • T is used as the object type or array element type in a new-expression (5.3.4), or T在new表达式(5.3.4)中用作对象类型或数组元素类型,或者
  • an lvalue-to-rvalue conversion is applied to a lvalue referring to an object of type T (4.1), or 左值到右值的转换应用于引用类型T(4.1)的对象的左值,或者
  • an expression is converted (either implicitly or explicitly) to type T (Clause 4, 5.2.3, 5.2.7, 5.2.9, 5.4), or 将表达式转换(隐式或显式)为类型T(第4条,5.2.3、5.2.7、5.2.9、5.4),或
  • an expression that is not a null pointer constant, and has type other than void*, is converted to the type pointer to T or reference to T using an implicit conversion (Clause 4), a dynamic_cast (5.2.7) or a static_cast (5.2.9), or 非空指针常量且类型不是void *的表达式将通过隐式转换(第4条),dynamic_cast(5.2.7)或static_cast( 5.2.9),或
  • a class member access operator is applied to an expression of type T (5.2.5), or 类成员访问运算符应用于类型T(5.2.5)的表达式,或者
  • the typeid operator (5.2.8) or the sizeof operator (5.3.3) is applied to an operand of type T, or 将typeid运算符(5.2.8)或sizeof运算符(5.3.3)应用于类型T的操作数,或
  • a function with a return type or argument type of type T is defined (3.1) or called (5.2.2), or 返回类型或参数类型为T的函数已定义(3.1)或称为(5.2.2),或者
  • a class with a base class of type T is defined (Clause 10), or 定义了一个具有T类型的基类的类(第10条),或者
  • an lvalue of type T is assigned to (5.17), or 类型T的左值分配给(5.17),或者
  • an exception-declaration has type T, reference to T, or pointer to T (15.3). 异常声明的类型为T,引用T或指向T的指针(15.3)。

In these cases, a forward declaration will not suffice and you need to fully define it. 在这些情况下,预先声明不够的,你需要完全定义它。

Is it needed? 需要吗?

Yes, in the cases where it is needed it is needed. 是的,在需要的情况下需要它。 In the following case it is, because both classes refer to each other. 在以下情况下,是因为两个类相互引用。

class A;

class B {
  // forward declaration needed
  void f(A);
};

class A {
  void f(B);
};

// "- a function with a return type or argument type of type T is defined"
void B::f(A) {

}

The member function definition required not only a declaration but also the definition of class A. 成员函数定义不仅需要声明,而且还需要类A的定义。

What are the benefits? 有什么好处? Drawbacks? 缺点?

The benefits are that your program compiles. 好处是您的程序可以编译。 The drawback is that you have polluted the scope with just another name. 缺点是您仅用另一个名称污染了范围。 But that's the necessary evil of it. 但这就是它的必要弊端。

If you refer to class by reference or pointer the compiler needs to know it exists but nothing else. 如果您通过引用或指针引用类,则编译器需要知道它的存在,但仅此而已。 Therefore all you need to do is forward declare it. 因此,您需要做的就是向前声明它。

If a file calls methods on a class or refers to object instances (not references or pointers) then the definition of that type must by pulled in with a #include. 如果文件在类上调用方法或引用对象实例(而不是引用或指针),则必须使用#include插入该类型的定义。

In a large codebase minimising #includes reduces compile time. 在大型代码库中,最小化#includes可减少编译时间。

Forward declarations also help avoid circular #include problems. 前向声明还有助于避免循环出现的#include问题。

If you are only going to reference that type, there's no need to pull in the entire header where it's defined, just use a forward declaration which tells the compiler "this is defined" so the compiler, when it comes along its usage in that file, and can't resolve the symbol, doesn't freak out on you. 如果仅引用该类型,则无需在定义的整个标头中提取数据,只需使用前向声明即可告诉编译器“已定义”,因此编译器在该文件中的用法,并且无法解析该符号,也不会吓到您。 It's one of those "I know what I'm doing" things. 这是“我知道我在做什么”的事情之一。

Forward declarations are essential when classes refer to each other. 当类彼此引用时,前向声明是必不可少的。 Here's a simple case: 这是一个简单的案例:

class A;

class B {
     void f(A&);
};

class A {
     void f(B&);
};

You couldn't do this without a forward declaration. 没有前瞻性声明,您将无法做到这一点。 It's the same as when you have two mutually recursive functions, one of them must be forward declared. 与具有两个相互递归的函数时相同,必须向前声明其中一个。

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

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