繁体   English   中英

朋友类或朋友成员函数 - 前向声明和头部包含

[英]Friend Class or Friend member function - Forward declaration and Header inclusion

是的,问题主题已被讨论了很多次。 而且我几乎清楚这种差异。 我只是怀疑与书中的一个例子有关。

这个问题与我之前的问题有关, 在C ++ Primer一书中提到了2个类。

在引用这些类时,本书引用了以下段落,特别是与WindowManager类的成员函数声明作为友元函数有关。 这就是它所说的:

使成员函数成为朋友需要仔细构造我们的程序以适应声明和定义之间的相互依赖性。 在这个例子中,我们必须按如下方式订购我们的程序:

  • 首先,定义Window_mgr类,它声明但无法定义,清除。 必须在clear之前声明屏幕才能使用Screen的成员。
  • 接下来,定义类Screen,包括clear的友元声明。
  • 最后,定义clear,现在可以引用Screen中的成员。

我在该问题中提出的代码仅遵循此结构。 但它似乎没有成功。 这让我想到如果以上几点是误导或我没有正确实现它。

问题是,当我在ScreenCls类中声明clear函数作为友元函数时,我会陷入头文件的循环包含 我将再次在这里简要介绍这两个类的具体部分:

ScreenCls.h:

#ifndef SCREENCLS_H
#define SCREENCLS_H

#include <iostream>

#include "WindowManager.h"

using namespace std;

class ScreenCls {
    friend void WindowManager::clear(ScreenIndex);

    // Some other code
}

这里我要包含WindowManager.h头文件,因为clear函数现在使用ScreenIndex定义的ScreenIndex 转发声明在这里不起作用(如果我错了,请纠正我)。

现在,接下来我们转到WindowManager.h

#ifndef WINDOWMANAGER_H
#define WINDOWMANAGER_H

#include <iostream>
#include <vector>
#include "ScreenCls.h"

using namespace std;

class WindowManager {
public:
    // location ID for each screen on window
    using ScreenIndex = vector<ScreenCls>::size_type;

private:
    vector<ScreenCls> screens{ ScreenCls(24, 80, ' ') };
};

并专注于这里的screens宣言。 他们使用列表初始化程序将默认的ScreenCls添加到vector 所以,我们再次需要包含WindowManager.h 现在我们进入循环包容。 这可以防止我的项目建立。

但是,如果我更改友元函数声明以使整个类成为朋友,那么我可以使用forward declaring WindowManager类。 在这种情况下,它会正常工作。

所以,基本上朋友功能在这里不起作用,但朋友班正在工作。 那么,以上几点对于它们的实现是不是很顺利,或者我的课程出了什么问题? 我只是想知道这一点,以清楚地理解header inclusionforward declaration的概念。

我之前的问题中提到的问题很好地描述了这一点。 但这只是因为它不能在上述情况下工作,所以我再次问它。

我想你的问题在于屏幕初始化程序。 您无法初始化类中的* .h文件中的任何数据。 所以,我建议你做那样的事情:

#ifndef WINDOWMANAGER_H
#define WINDOWMANAGER_H

#include <iostream>
#include <vector>
//#include "ScreenCls.h"

using namespace std;
class ScreenCls;

class WindowManager {
public:
    // location ID for each screen on window
    using ScreenIndex = vector<ScreenCls>::size_type;

private:
    vector<ScreenCls> screens; //{ ScreenCls(24, 80, ' ') };    remove this
};

只要您没有使用该类,即调用对象上的方法或调用new实例或保留类的实例数组,您只能使用前向声明。 作为tumb的规则:如果编译器在使用前向声明时没有抱怨,请使用它们并避免包含哪些减慢编译速度。

只有危险:当你使用多重继承并且没有包含时,强制转换将无法正常工作 - 但通常你会在.cpp中进行,你应该包含你使用的类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM