我最近刚刚了解了C++中的friend class
概念(我在谷歌上搜索了一下,但这个答案让我笑了,直到我想起了最重要的部分),我正试图将它融入到我现在正在进行的项目中。简洁的问题在最后被单独列出,但总的来说,我对工作代码中完全缺乏前向声明感到困惑。
我的所有类都通过(子)文件夹进行分离,每个类都被分为一个单独的.h和.cpp文件,但这应该足以让我感受到依赖性:
// FE.h - no implementations - no .cpp file
class FE
{
private:
virtual void somePrivateFunc() = 0;
// 90% virtual class, interface for further implementations
friend class TLS;
};
// DummyFE.h
#include "FE.h"
class DummyFE :: public FE {
/* singleton dummy */
private:
// constructor
public:
static DummyFE& instance();
};
// DummyFE.cpp
#include "DummyFE.h"
// all Dummy FE implementation
// ImplFE.h
#include "FE.h"
class ImplFE :: public FE { /* implemented */ };
// ImplFE.cpp
#include "FE.cpp"
// all Impl FE implementations
// SD.h - implements strategy design pattern
// (real project has more than just FE class in here)
#include "FE.h"
#include "DummyFE.h"
class SD
{
private:
FE &localFE;
public:
SD(FE ¶mFE = DummyFE::instance());
// ... and all the other phun stuff ...
friend class TLS;
};
// SD.cpp - implementations
# include "SD.h"
/* SD implemented */
// TLS.h - implements strategy design pattern
(on a higher level)
#include SD.h
class TLS{
private:
SD *subStrategy;
public:
void someFunctionRequiringFriendliness();
}
// TLS.cpp - implementations
#include "TLS.h"
void TLS::someFunctionRequiringFriendliness(){
this->subStrategy->localFE.somePrivateFunc(); // ok!
}
现在,我已经让一方使用所有的依赖项来实际编译所有这些(最后必须将其写在类图中才能使其工作),但现在它做到了。事实上,让我感到困惑的是不需要前向声明。我以前就知道正向声明,为了以防万一,我用这个答案刷新了我的记忆。
因此,为了保持清楚,我的问题:当声明class TLS
为友元时,为什么不需要显式的正向声明?这是否意味着friend class
声明本身就是一个正向声明?对我来说,凭直觉,这里缺少了一些东西。。。既然它能正常编译和工作,有人能帮助纠正我的直觉吗?:D
PS很抱歉对这个问题和一堆代码做了这么长的介绍。请不要评论我的代码概念——朋友们在这里很好,我很确定这对我当前的项目是正确的(只是从这个框架中很难看出)。我只是想知道为什么任何地方都不需要远期申报。
你说得对,友元声明有点像正向声明。
以下编译:
class A;
class B
{
friend A;
};
或
class B
{
friend class A;
};
这不是:
class B
{
friend A;
};
friend
声明转发声明class A
,而是class
关键字。这就是为什么第二个例子不起作用,因为它不知道A
是什么。如果你像第一个片段一样预先声明A
,它可以将A
解析为类声明我被纠正了。
friend class TLS;
此语法本身就是一个声明,这就是为什么您不需要该类型的额外先前声明。请注意,friend
声明与封闭命名空间中的声明略有不同(特别是对于函数)。
特别是,除非封闭命名空间中也有声明,否则在friend
声明中声明的函数只能通过依赖于参数的查找找到(并且不能在类之外定义)。类也是如此,除非在命名空间级别也有声明,否则这样声明的类型在将其声明为友元的类之外将不可用。
class B {
friend class A;
};
//A foo(); // Error: A is not declared here!
class A;
A foo(); // Fine
这是否意味着友元类声明是转发宣言本身?
是
正向声明不需要位于文件的顶部,如下所示
class A;
class C;
class D;
class B
{
A* a;
C* c;
D* d;
};
与相同
class B
{
class A* a;
class C* c;
class D* d;
};
推荐的friend语法只使用后面的