12

我最近刚刚了解friend class了 C++ 中的概念(我用谷歌搜索了一下,但这个答案让我发笑,直到我记住了最重要的部分),我正试图将它融入我的项目中现在正在工作。简洁的问题最后被挑出来,但总的来说,我对我的工作代码中完全缺乏前向声明感到困惑。

我的所有类都通过(子)文件夹分开,每个类都放在单独的.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很抱歉对这个问题和一堆代码进行了如此冗长的介绍。请不要评论我的代码概念 - 朋友们在这里很好,我很确定这对我当前的项目是正确的(从这个骨架中很难看出)。我只想知道为什么在任何地方都不需要前向声明。

4

4 回答 4

7

你是对的,朋友声明有点像前向声明。

以下编译:

class A;
class B
{
   friend A;
};

或者

class B
{
   friend class A;
};

这不会:

class B
{
   friend A;
};

forward-declares实际上不是friend声明class A,而是class关键字。这就是为什么第二个示例不起作用的原因,因为它不知道是什么A。如果您A事先声明,就像在第一个片段中一样,它可以解析A为类声明。

我站得更正了。

于 2012-03-27T13:47:34.420 回答
7
friend class TLS;

此语法本身就是一个声明,这就是为什么您不需要额外的先前类型声明的原因。请注意,friend声明与封闭命名空间中的声明略有不同(特别是对于函数)。

特别是,除非在封闭的命名空间中也有声明,否则声明中声明的函数friend只能通过参数相关查找找到(并且不能在类之外定义)。类也是如此,除非在命名空间级别也有声明,否则这样声明的类型在将其声明为友元的类之外将不可用。

class B {
   friend class A;
};
//A foo();    // Error: A is not declared here!
class A;
A foo();      // Fine
于 2012-03-27T13:48:59.660 回答
3

前向声明不需要在文件顶部如下

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;
};

推荐的朋友语法只使用后者

于 2012-03-27T13:56:06.343 回答
2

这是否意味着一个朋友类声明本身就是一个前向声明?

是的

于 2012-03-27T13:48:00.473 回答