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

时间:2013-05-14 19:28:40

标签: c++ build header-files codeblocks

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

这个问题与my previous question有关,我在C ++ Primer一书中以2个类为例。

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

  

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

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

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

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

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的声明。他们使用 list initializer ScreenCls添加默认vector。所以,我们再次需要包含WindowManager.h。现在我们进入循环包容。这可以防止我的项目构建。

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

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

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

2 个答案:

答案 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中进行,你应该包含你使用的类。