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