C++正向声明一个类?

问题描述 投票:0回答:4

在 .h 中如果我有:

#pragma once

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

class AAAAAA;
class BBBBBB;

class ZZZZZZ
{
     public:

     // etc
 };

使用AAAAAA级;向前声明一个类是对的吗?

为什么要这样做?

需要吗?

有什么好处?缺点?

c++ forward-declaration
4个回答
2
投票

为什么要这样做?

因为编译器只知道已声明的名称。所以如果你想使用一个类,你必须声明它。但是,如果它的定义取决于它的用户,如果用户不依赖于类的定义,而只依赖于它的声明(=名称),则前向声明就足够了。

特别是,如果用户只需要一个指针或引用,则它不依赖于定义。但在列出的情况下(不声称是排他性的,因为它是标准的非规范摘录),用户依赖于类 T 的定义 if

  • 定义了 T 类型的对象 (3.1),或者
  • T 在 new 表达式 (5.3.4) 中用作对象类型或数组元素类型,或者
  • 左值到右值的转换应用于引用类型 T (4.1) 的对象的左值,或者
  • 表达式被转换(隐式或显式)为 T 类型(第 4、5.2.3、5.2.7、5.2.9、5.4), 或
  • 非空指针常量且类型不是 void* 的表达式将转换为 使用隐式转换(第 4 条)、dynamic_cast (5.2.7) 或 类型指向 T 的指针或对 T 的引用 static_cast (5.2.9),或
  • 将类成员访问运算符应用于类型 T (5.2.5) 的表达式,或者
  • typeid 运算符 (5.2.8) 或 sizeof 运算符 (5.3.3) 应用于 T 类型的操作数,或者
  • 定义(3.1)或调用(5.2.2)返回类型或参数类型为 T 的函数,或者
  • 定义了一个具有 T 类型基类的类(第 10 条),或者
  • 类型 T 的左值被分配给 (5.17),或者
  • 异常声明具有类型 T、对 T 的引用或指向 T 的指针 (15.3)。

在这些情况下,前向声明不够,您需要完整定义它。

需要吗?

是的,在需要的情况下是需要的。在下面的情况下是这样,因为两个类互相引用。

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) {

}

成员函数定义不仅需要声明,还需要类 A 的定义。

有什么好处?缺点?

好处是你的程序可以编译。缺点是您用另一个名称污染了范围。但这是它必要的邪恶。


2
投票

如果通过引用或指针引用类,编译器需要知道它存在,但不需要知道其他任何信息。 因此,您需要做的就是向前声明它。

如果文件调用类上的方法或引用对象实例(不是引用或指针),则必须使用 #include 引入该类型的定义。

在大型代码库中,最小化 #include 可以减少编译时间。

前向声明还有助于避免循环 #include 问题。


0
投票

如果您只想引用该类型,则无需提取定义该类型的整个标头,只需使用前向声明来告诉编译器“已定义此类型”,以便编译器在出现该类型的用法时文件,并且无法解析该符号,不会吓到你。这是“我知道我在做什么”的事情之一。


0
投票

当类相互引用时,前向声明至关重要。 这是一个简单的案例:

class A;

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

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

如果没有前向声明,你就无法做到这一点。 这就像当你有两个相互递归的函数时,其中一个必须向前声明。

© www.soinside.com 2019 - 2024. All rights reserved.