C ++ Forward声明一个类?

时间:2010-09-04 17:06:41

标签: c++ compiler-construction forward-declaration

如果我有一个.h:

#pragma once

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

class AAAAAA;
class BBBBBB;

class ZZZZZZ
{
     public:

     // etc
 };

使用AAAAAA类;是前进宣布一个班级吗?

为什么会这样做?

需要它吗?

有什么好处?缺点

4 个答案:

答案 0 :(得分:3)

  

为什么会这样做?

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

特别是,如果用户只需要指针或引用,则它不依赖于定义。但是在列出的案例中(由于它是标准的非规范性摘录,因此不会声称是排他性的),用户依赖于T类的定义

  • 类型T的对象定义为(3.1)或
  • T用作new-expression(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的操作数,或
  • 具有类型T的返回类型或参数类型的函数定义为(3.1)或调用(5.2.2),或
  • 定义类型为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类的定义。

  

有什么好处?缺点

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

答案 1 :(得分:3)

如果您通过引用或指针引用类,编译器需要知道它存在但没有别的。因此,您需要做的就是向前声明它。

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

在大型代码库中,最小化#includes会缩短编译时间。

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

答案 2 :(得分:0)

如果你只是要引用那个类型,就没有必要在它定义的位置拉入整个头文件,只需使用一个前向声明来告诉编译器“这是定义的”所以当编译器出现它的用法时在那个文件中,无法解析符号,不会吓到你。这是“我知道我在做什么”的事情之一。

答案 3 :(得分:0)

当课程相互引用时,前向声明是必不可少的。这是一个简单的案例:

class A;

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

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

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