首页 > 代码库 > c++ primer,友元函数上的一个例子(By Sybase)

c++ primer,友元函数上的一个例子(By Sybase)

本文试图解释c++ primer Screen 和 Window_Mgr的例子,为什么将两个类放在两个文件中无法编译?

将两个类写在同一个文件中,通过三个例子解释问题:

第一种写法问题:

编译到Screen时,由于Screen类使用到Window_Mgr的成员函数,虽然前面给出了Window_Mgr的声明,但此时还清楚Window_Mgr的完整定义,所以编译出错。

class Window_Mgr

class Screen

{

  public:

    friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);

  private:

    int height;

    int width;

}

class Window_Mgr

{

public:

  typedef std::string::size_type index;

  Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)

  {

    s.height += r;

    s.width += c;

    return *this;

  }

}

 

第二种写法问题在于:

编译到relocate时,由于Screen& s的实现使用到Screen的成员变量,虽然前面给出了Screen的声明,但此时还清楚Screen的完整定义,所以编译出错。

 

class Screen;

class Window_Mgr

{

public:

  typedef std::string::size_type index;

  Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)

  {

    s.height += r;

    s.width += c;

    return *this;

  }

}

class Screen

{

  public:

    friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);

  private:

    int height;

    int width;

}

第三种写法:

将Window_Mgr::relocate的实现移动到最后,由于编译类Window_Mgr时,并不需要Screen&s 的实现细节,问题得到解决

class Screen;

class Window_Mgr

{

public:

  typedef std::string::size_type index;

  Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s);

}

class Screen

{

  public:

    friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);

  private:

    int height;

    int width;

}

 

 

  Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s)

  {

    s.height += r;

    s.width += c;

    return *this;

  }

 

可见,这两个类如果编译成功需要严格的交替顺序

这也就解释了为什么放在两个文件中无法编译。

 

附录:

一开始的实现的不能编译的两个文件

实现分别如下:Window_Mgr.h

#ifndef WINDOW_MGR //为了避免两个文件嵌套

#define WINDOW_MGR

#include <string>

#include <Screen.h>

class Window_Mgr

{

public:

  typedef std::string::size_type index;

  Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)

  {

    s.height += r;

    s.width += c;

    return *this;

  }

}

#endif

Screen.h

#ifndef SCREEN

#define SCREEN

#include "Window_Mgr.h"

class Screen

{

  public:

    friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);

  private:

    int height;

    int width;

}

#endif