无法将类的方法定义为另一个类的朋友

时间:2012-06-02 16:45:00

标签: c++ friend access-control

我正在尝试将MainScheduler的方法addJob作为Job类的友元函数,如下所示:

#include "MainScheduler.h"
//forward declaration
class MainScheduler;

class Job:
{
    friend void MainScheduler::addJob( Job* const job );
    ...
}

但我一直收到错误

  

错误C2027:使用未定义类型'MainScheduler'

你知道我为什么收到这条消息,我该如何解决?

2 个答案:

答案 0 :(得分:5)

您只能命名已声明的成员函数,即使是友情声明也是如此。这意味着必须定义类,而不仅仅是前向声明。

错:

class X;

class Y
{
    friend void X::f(); // ERROR
};

右:

class X
{
public:
    void f();
};

class Y
{
    friend void X::f();
};

为什么#include "MainScheduler.h"没有明确class MainScheduler的定义,这是不明显的,所以还有其他奇怪的事情发生在那里。

此规则意味着无法执行A::f()B的朋友而B::g()的朋友是A的朋友,所以有时你只需要满足于整个班级的朋友。 (或者有一些奇特的方法可以使用辅助类来请求/授予某些函数集的权限,但是当你需要一个可扩展的库接口时,这会更有用。)

答案 1 :(得分:2)

问题很简单:你不能有依赖循环。

// MainScheduler.h
#ifndef MAINSCHEDULER
#define MAINSCHEDULER

#include "Job.h"

class MainScheduler { friend class Job; };

#endif


// Job.h
#ifndef JOB
#define JOB

#include "MainScheduler.h"

class Job { friend class MainScheduler; };

#endif

解析MainScheduler.h时会发生以下情况:

  • MAINSCHEDULER未定义,因此解析开始
  • 预处理器定义MAINSCHEDULER
  • 预处理器包括Job.h
  • 因为MAINSCHEDULER已经定义,所以它会跳过包含MainScheduler.h
  • 它包含来自Job
  • 的令牌
  • 包括Job.h结束
  • 它包含来自MainScheduler
  • 的令牌

这会产生以下预处理器输出,编译器会看到:

// ignored #include "MainScheduler.h"

class Job { friend class MainScheduler; };

class MainScheduler { friend class Job; };

这就是为什么在你引入前向声明之前,编译器在MainScheduler的定义中抱怨了未知的Job符号。

您的标题不能包含在一个循环中,并且您不能仅使用前向声明与成员函数成为朋友。

我建议你将Job.h重写为:

class MainScheduler; // forward declaration

class Job {
    friend class MainScheduler;
public:
    // whatever

};

通过与全班同学,你只需要一个前瞻宣言就可以逃脱,并打破这个循环。