Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 友元类或友元成员函数-转发声明和标头包含_C++_Build_Header Files_Codeblocks - Fatal编程技术网

C++ 友元类或友元成员函数-转发声明和标头包含

C++ 友元类或友元成员函数-转发声明和标头包含,c++,build,header-files,codeblocks,C++,Build,Header Files,Codeblocks,是的,这个问题已经讨论过很多次了。我几乎很清楚两者的区别。我只对书中的一个例子有一个疑问 这个问题与我在C++入门书中所举的2个类有关。p> 关于这些类,本书引用了以下段落,特别是与WindowManager类的成员函数声明为友元函数有关。它是这样说的: 让一个成员函数成为朋友需要仔细地构建我们的程序,以 适应声明和定义之间的相互依赖性。在这个 例如,我们必须按如下方式订购我们的计划: 首先,定义Window_mgr类,该类声明但不能定义clear。 必须先声明Screen,然后clear才能

是的,这个问题已经讨论过很多次了。我几乎很清楚两者的区别。我只对书中的一个例子有一个疑问

这个问题与我在C++入门书中所举的2个类有关。p> 关于这些类,本书引用了以下段落,特别是与
WindowManager
类的成员函数声明为友元函数有关。它是这样说的:

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

  • 首先,定义Window_mgr类,该类声明但不能定义clear。 必须先声明Screen,然后clear才能使用Screen的成员
  • 接下来,定义类屏幕,包括用于清除的好友声明
  • 最后,定义clear,它现在可以引用屏幕中的成员
我在那个问题中提出的代码仅遵循此结构。但它似乎不起作用。这让我想,如果以上几点是误导,或者我没有正确地实施它

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

ScreenCls.h: 然后集中在这里的
屏幕的声明上。他们使用列表初始值设定项将默认的
ScreenCls
添加到
向量
。因此,这里再次需要包含
WindowManager.h
。现在我们进入循环包含。这使我的项目无法构建

但是,如果我更改friend函数声明使整个类成为friend,那么我可以使用
正向声明
WindowManager
类。那样的话,它就可以正常工作了

所以,基本上朋友函数在这里不起作用,但朋友类在起作用。那么,是因为上述几点的实现不顺利,还是我的类出了问题?我只想知道这一点,以便清楚地理解
标题包含
转发声明
的概念


我上一个问题中的相关问题很好地描述了这一点。但这只是因为它在上述情况下不起作用,所以我再问一遍。

只要您不使用该类,即调用对象上的方法或调用新实例或保留该类的实例数组,您就只能使用前向声明。tumb的一条规则是:如果编译器在使用前向声明时没有抱怨,请使用前向声明,并避免包含会减慢编译速度


唯一的危险:当您使用多重继承进行强制转换并且没有include时,强制转换将不能很好地工作-但这通常会在.cpp中进行,您应该在其中包含您使用的类。

我猜您的问题在于屏幕初始值设定项。不能初始化类中*.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
};
\ifndef WINDOWMANAGER\u H
#定义WINDOWMANAGER\u H
#包括
#包括
//#包括“ScreenCls.h”
使用名称空间std;
类别CLS;
类窗口管理器{
公众:
//窗口上每个屏幕的位置ID
使用ScreenIndex=vector::size\u type;
私人:
矢量屏幕;/{ScreenCls(24,80,,)};删除此
};

是的,很好。但我想知道的是,由于ScreenCls目前的状态,
clear
函数声明要求包含
WindowManager
,而不是向前声明,对吗?在这种情况下,存在循环依赖关系。但是,如果我们使用
朋友类WindowManager而不是当前的友元成员函数声明,那么转发声明就可以了。对吗?这需要检查,但我会说不。当你写这个朋友时,你只是在类WindowManager中声明,如果有一个方法清除,它将能够调用私有或受保护的方法。我想你在这里指的是“ScreenCls.h”:“所以,这里我们再次需要包含WindowManager.h”@psibar。对。谢谢你的指点。编辑:)@psibar。我认为我们不能做那样的事<代码>屏幕索引
是WindowManager类中定义的类型别名。我们只能向前声明一个类或函数(从我读到现在为止)。我遇到了同样的问题。我认为书中提供的解决方案是错误的。我们不能那样做。
#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, ' ') };
};
#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
};