c++ - 如何声明两个类使得 A 具有 B 的成员并且 B 将 A 的成员标记为 friend ?

标签 c++ class friend forward-declaration

我正在尝试做 C++ Primer 第 5 版中的练习 7.32。该练习要求以下内容:

Define your own versions of Screen and Window_mgr in which clear is a member of Window_mgr and a friend of Screen.

下面是文中给出的ScreenWindow_mgrclear的定义。

class Screen
{
  public:
    using pos = std::string::size_type;
    Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) { }
  private:
    pos height = 0, width = 0;
    std::string contents;
};

class Window_mgr
{
  public:
    using ScreenIndex = std::vector<Screen>::size_type;
    void clear(ScreenIndex);
  private:
    std::vector<Screen> screens{Screen(24, 80 ' ')};
};

void Window_mgr::clear(ScreenIndex i)
{
  Screen &s = screens[i];
  s.contents = std::string(s.height * s.width, ' ');
}

现在这两个类,如果首先定义 Screen 而不是 Window_mgr,则按我预期的那样工作。现在,练习要求我使 clear 成为 Screen 的友元并定义 clear。要使明确一个成员成为 friend ,如果我理解正确的话,必须定义Window_mgr。要定义 Window_mgr,必须定义 Screen。这对我来说似乎是不可能的。

文中给出了以下提示:

Making a member function a friend requires careful structuring of our programs to accommodate interdependencies among the declarations and definitions. In this example, we must order our program as follows:

  • First, define the Window_mgr class, which declares, but does not define, clear. Screen must be declared before clear can use members of Screen.

  • Next, define class Screen, including a friend declaration for clear.

  • Finally, define clear, which can now refer to members in Screen.

我尝试解决这个练习的顺序最终是这样的:

class Screen;

class Window_mgr
{
  public:
    using ScreenIndex = std::vector<Screen>::size_type;
    void clear(ScreenIndex);
  private:
    std::vector<Screen> screens{Screen(24, 80 ' ')};
};

class Screen
{
  friend Window_mgr::clear(Window_mgr::ScreenIndex);
  public:
    using pos = std::string::size_type;
    Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) { }
  private:
    pos height = 0, width = 0;
    std::string contents;
};

void Window_mgr::clear(ScreenIndex i)
{
  Screen &s = screens[i];
  s.contents = std::string(s.height * s.width, ' ');
}

这显然行不通,因为 Window_mgr 中的 vector 需要 Screen 是一个完整的类型。这似乎是一项无法解决的练习,除非作者不打算使用他们之前提供的 ScreenWindow_mgr 类。

有没有其他人通过 C++ Primer 解决了这个练习。如果是这样,如何?任何帮助如何做到这一点,或者正如我的直觉告诉我,不能做到这一点?

最佳答案

正如 [class.friend]/5 所说:

When a friend declaration refers to an overloaded name or operator, only the function specified by the parameter types becomes a friend. A member function of a class X can be a friend of a class Y.

在您的具体情况下:

#include <iostream>
#include <vector>

struct Screen;

class Window_mgr
{
  public:

    Window_mgr();

    using ScreenIndex = std::vector<Screen>::size_type;
    void clear(ScreenIndex);
  private:
    std::vector<Screen> screens;
};

class Screen
{
  friend void Window_mgr::clear(ScreenIndex);
  public:
    using pos = std::string::size_type;
    Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) { }
  private:
    pos height = 0, width = 0;
    std::string contents;
};


Window_mgr::Window_mgr():
  screens{1, Screen(24, 80, ' ') }
{
}

void Window_mgr::clear(ScreenIndex i)
{
  Screen &s = screens[i];
  s.contents = std::string(s.height * s.width, ' ');
}

int main()
{
  Window_mgr w;
  w.clear(0);
}

请注意,该练习无法解决,因为 Window_mgr 有一个 std::vector 成员变量,该参数是不完整类型。它适用于大多数编译器(参见 here 为什么),但标准禁止它。

这个例子演示了如何使一个类的成员函数成为友元:

#include <iostream>

struct A;

struct B
{ 
  void bar( A& a, int l);
};

struct A
{
  friend void B::bar(A&,int);
  A():k(0){}
  private:
  void foo(int m);
  int k;
};



void A::foo(int m)
{
  std::cout<<"A::foo() changing from "<<k<<" to "<<m<<std::endl;
  k=m;
}

void B::bar( A& a, int l)
{
  std::cout<<"B::bar() changing to "<<l<<std::endl;
  a.foo(l);
}

int main()
{
  A a;
  B b;
  b.bar(a,11);
}

关于c++ - 如何声明两个类使得 A 具有 B 的成员并且 B 将 A 的成员标记为 friend ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18905090/

相关文章:

c++ - 如何将 Linux C++ 源代码转换为 Windows C++ 源代码?

c++ - 从基类继承私有(private)成员

c++ - 找不到匹配项

c++ - 为 Mac OS X 设置 WindowsHookEx?

c++ - 编译器不同意接受此 View ::keys 代码

C++ friend 继承?

c++ - C++ 中的友元作用域

c++ - "friend"一个类是否扩展到该类中声明的类?

c++ - 如何使类的函数成为默认值

r - 从 SpatialPolygons 和其他 sp 类中提取特征坐标