朋友类概念不需要声明

How come forward declaration is not needed for friend class concept?

本文关键字:不需要 声明 朋友      更新时间:2023-10-16

我最近刚刚了解了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 &paramFE = 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语法只使用后面的