包含在头文件与前向声明中,并包含在.cpp中

col*_*die 29 c++ header-files

我有一个B类,我想把成员称为A类.所以:

1.

//A.h    
class B; 
class A 
{ 
private:
    B* m_p; 
}; 

//a.cpp
#include "B.h"
Run Code Online (Sandbox Code Playgroud)

2.

// A.h
#include "B.h"

class A 
{ 
private: 
    B * impl_; 
}; 
Run Code Online (Sandbox Code Playgroud)

当一个没有太多依赖性的小项目涉及时,这两种方式是否更好?

jog*_*pan 33

你做的第一种方式是指在a.h中,存在class B是已知的,但不是它的定义.这限制了你可以用B内部做什么a.h.例如,您可以拥有类型的变量B *,但不能具有类型的变量B(因为对于类型变量的声明,B编译器必须能够看到完整定义B).此外,如果您有类型的变量B *,则不能取消引用指针(因为这样,B必须知道定义).

因此,您的第二选择 - 没有这些问题 - 是首选,这是大多数人大多数时间使用的.

这是第一种方法可能有用的特殊情况.例如:

  • 如果.h文件互相包含(但是你可能会遇到一些其他的问题,也就是包含防范问题;这通常很难并且要避免);
  • 如果b.h非常大且复杂,那么您希望尽可能避免包含它,因为它会降低编译过程的速度.


mad*_*tya 17

你的第一种方法是前瞻性声明.你的第二个实际上包括B班.

何时使用一个而不是另一个?

使用第一个时:

  • 在A 的定义中,您只有一个指向B的指针,即不是B的成员.
  • 你永远不会从A 的定义中调用B的任何函数.(即对B的成员函数的所有调用都发生在实际实现A的成员函数的.cpp文件中.)
  • 你希望B类的接口或大小经常改变,但不是A的接口.这样,如果B改变,只有a.cpp的内容得到重新编译,但啊(和其他包含啊的文件)不需要改变.

在以下情况下使用第二个:

  • 您需要知道B 的大小.编译器使用其类定义及其所有成员的大小来计算类的大小.例如,如果类A具有类型B的成员,那么为了计算A的大小,编译器需要知道B的大小; 要知道B的大小,你需要包括bh
    • 你需要调用类B的函数.为了知道你是否正在调用实际存在的函数,编译器需要知道B类的接口,即你需要包含bh


And*_*olk 11

答案:1.
看看http://www.umich.edu/~eecs381/handouts/handouts.html

C头文件指南

C++头文件指南(密歇根大学EECS部门David Kieras)说:

准则#10.如果X类型的声明不完整,请使用它而不是#including其标题Xh.如果另一个结构或类类型X在头文件的内容中仅作为指针或引用类型出现,那么你不应该#include Xh,而只是在附近放置一个不完整的X声明(也称为"前向"声明).标题文件的开头,如下所示:class X;有关这一功能强大且有价值的技术的更多讨论,请参阅讲义 不完整声明.请注意,标准库包含一个不完整声明的标题,这些声明通常用于<iostream> 命名库的库<iosfwd>.<iosfwd>尽可能#include ,因为<iostream>标题文件非常大(巨型模板!).