是的问题主题已经讨论过很多次了。而且我几乎清楚这种差异。我只有一个疑问与书中的例子有关。
这个问题与my previous question有关,我在C ++ Primer一书中以2个类为例。
在引用这些类时,本书引用了以下段落,特别是与WindowManager
类的成员函数声明为友元函数有关。这就是它所说的:
使成员函数成为朋友需要仔细构建我们的程序 适应声明和定义之间的相互依赖关系。在这 例如,我们必须按如下方式订购我们的计划:
- 首先,定义Window_mgr类,它声明但无法定义,清除。 必须在clear之前声明屏幕才能使用Screen的成员。
- 接下来,定义类屏幕,包括明确的朋友声明。
- 最后,定义clear,现在可以引用Screen中的成员。
我在该问题中提出的代码仅遵循此结构。但它似乎没有成功。这让我想到如果以上几点是错误的,或者我没有正确实现它。
问题是,当我在clear
类中声明ScreenCls
函数作为友元函数时,我会陷入头文件的循环包含。我将再次在这里简要介绍这两个课程的具体部分:
#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
。 前瞻声明在这里不起作用(如果我错了,请纠正我)。
现在,接下来我们转到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
的声明。他们使用 list initializer 向ScreenCls
添加默认vector
。所以,我们再次需要包含WindowManager.h
。现在我们进入循环包容。这可以防止我的项目构建。
但是,如果我更改友元函数声明以使整个班级成为朋友,那么我可以使用forward declaring
WindowManager
类。在这种情况下,它会正常工作。
所以,朋友的功能基本上不在这里,但朋友班正在工作。那么,以上几点对于它们的实现是不是很顺利,或者我的课程出了什么问题?我只是想知道这一点,以便清楚地理解header inclusion
和forward declaration
的概念。
我之前提出的问题中的问题很好地描述了这一点。但这只是因为它不能在上述情况下工作,所以我再次问它。
答案 0 :(得分:2)
我猜您的问题在于屏幕初始化程序。您无法初始化类中的* .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
};
答案 1 :(得分:1)
只要您不使用该类,即在对象上调用方法或调用new或者保留类的实例数组,您只能使用前向声明。作为tumb的规则:如果编译器在使用前向声明时没有抱怨,请使用它们并避免包含哪些减慢编译。
只有危险:当你使用多重继承并且没有包含时,强制转换将无法正常工作 - 但通常你会在.cpp中进行,你应该包含你使用的类。