【发布时间】:2023-11-19 04:35:01
【问题描述】:
当一个类声明仅使用另一个类作为指针时,使用类前向声明而不是包含头文件以预先避免循环依赖问题是否有意义?所以,而不是:
//file C.h
#include "A.h"
#include "B.h"
class C{
A* a;
B b;
...
};
改为这样做:
//file C.h
#include "B.h"
class A;
class C{
A* a;
B b;
...
};
//file C.cpp
#include "C.h"
#include "A.h"
...
有什么理由不尽可能地这样做吗?
【问题讨论】:
-
嗯 - 这是顶部还是底部问题的答案?
-
你真正的问题(在底部) - AFAIK 在这种情况下没有理由不使用前向声明......
-
这稍微取决于“仅将另一个类用作指针”的意思。有一个令人讨厌的情况,您可以仅使用前向声明来
delete指针,但如果该类实际上具有非平凡的析构函数,那么您将得到 UB。所以如果delete“只使用指针”那么是的,这是有原因的。如果不算数,也不算数。 -
循环依赖不是还在,只是对编译器隐藏了吗?如果是的话,这两种策略总是包括并总是做前向声明并不会教你如何避免循环依赖。但是我必须承认,使用前向声明它们可能更容易找到。
-
如果类是 A 实际定义为结构,一些编译器可能会抱怨。如果 A 类是派生类,那么您就有问题了。如果类 A 定义在另一个命名空间中,并且标头只是使用 using 声明将其拉入此命名空间,则您可能会遇到问题。如果 A 类实际上是别名(或宏!),那么您就有问题了。如果 A 类实际上是一个 typedef,那么你就有问题了。如果 A 类实际上是具有默认模板参数的类模板,那么您就有问题了。是的,不转发声明是有原因的:它破坏了实现细节的封装。