友类或友成员函数-前向声明和包含头
Friend Class or Friend member function - Forward declaration and Header inclusion
这个问题已经被讨论了很多次了。我几乎很清楚它们之间的区别。我对书中的一个例子只有一个疑问。
这个问题与我之前的问题有关,我在《c++入门》一书中给出了2个类作为例子。
对于这些类,书中引用了以下段落,特别涉及到将WindowManager
类的成员函数声明为友元函数。它是这样写的:
将成员函数设置为友元需要对程序进行仔细的构造适应声明和定义之间的相互依赖关系。在这个例如,我们必须按如下方式对程序进行排序:
- 首先,定义Window_mgr类,它声明,但不能定义clear。Screen必须在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
。前向声明在这里不起作用(如果我错了请纠正我)。
现在,我们继续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 inclusion
和forward 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 for instance或保留类的实例数组,你可以只使用前向声明。作为一个经验法则:如果你使用前向声明时编译器没有报错,那么就使用它们,并避免使用会减慢编译速度的include。
唯一的危险:当您使用多重继承进行强制转换而没有包含时,强制转换将不能很好地工作-但这通常会在您应该包含您使用的类的.cpp中进行。
- 使用mongocxx驱动程序时包含头文件问题
- 如何为包含头文件的目标编写生成文件?
- 如何在 CMakeLists.txt Qt Creator 中包含头文件?
- 枚举前向声明与头文件
- 当包含头文件的文件不在根项目文件夹中时,如何包含它
- 在生成文件先决条件中包含头文件的原因
- My Project的属性配置正确,但Visual Studio仍然无法打开包含头文件
- 在 PostgreSQL C 扩展中包含头文件
- 是否可以在C++中以间接方式包含头文件
- 是否需要包含头文件?
- boost::hana 转发声明标头的用例是什么?
- 我收到未声明的标识符错误,但我已包含头文件?
- 为什么我们需要构建一个提升库,仅仅包含头文件还不够吗,因为提升是模板
- 如何声明包含整数数组的对象
- 为什么要将包含的类声明为头文件
- 创建并包含一个带有函数声明的头文件,然后是一个带有定义的源文件,然后是另一个带有函数调用的源文件
- 友类或友成员函数-前向声明和包含头
- 即使包含头文件,_mm_shuffle_ps也没有声明
- 在类声明/定义中包含头文件
- 包含malloc声明的头文件的名称是什么?