如何声明两个类,使A有B和B的成员标记A的成员作为朋友? [英] How to declare two classes such that A has members of B and B marks members of A as friends?

查看:217
本文介绍了如何声明两个类,使A有B和B的成员标记A的成员作为朋友?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从C ++ Primer第5版练习7.32。该练习询问以下内容:

I am attempting to do exercise 7.32 from C++ Primer 5th Edition. That exercise asks the following:


定义您自己的版本 Screen Window_mgr 其中 clear Window_mgr 的成员, 屏幕。

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

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工作,现在,该练习要求我让清除 Screen的一个朋友,并定义 clear 。要使清除成员的朋友,如果我理解正确,必须定义 Window_mgr 。要定义 Window_mgr ,必须定义屏幕。这对我来说是不可能的。

Now those two classes, if defined Screen first than Window_mgr work as I expect. Now, the exercise asks me to make clear a friend of Screen and define clear. To make clear a member a friend, if I understand correctly, Window_mgr must be defined. To define Window_mgr, Screen must be defined. This seems impossible to me.

文本提供以下提示:


使成员函数成为朋友需要仔细构造我们的程序以适应声明和定义之间的相互依赖。在这个例子中,我们必须按如下顺序订购程序:

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:


  • 首先,定义 Window_mgr 类,它声明但不定义 clear 必须在清除之前声明才能使用屏幕

接下来,定义类 Screen ,包括 clear c>。

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

最后,定义 clear 屏幕中。

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

The order in which I attempted to solve this exercise was ultimately this:

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 ,需要屏幕才能成为一个完整的类型。这似乎是一个无法解决的练习,除非作者不打算使用他们之前提供的 Screen Window_mgr 类。

This obviously would not work, due to the vector in Window_mgr that needs Screen to be a complete type. This seems like an unsolvable exercise, unless the authors do not intend one to use Screen and Window_mgr classes they present earlier.

有没有人从C ++ Primer中解决这个练习。如果是,如何?

Has anyone else solved this exercise from C++ Primer. If so, how? Any help how this can be done, or as my gut tells me, cannot be done?

推荐答案

As [class.friend]如果这样做可以完成或者我的直觉告诉我, / 5说:

As [class.friend]/5 says :


当朋友声明引用重载的名称或操作符时,只有参数类型指定的函数成为朋友。类X的成员函数可以是类Y的朋友。

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的参数是一个不完整的类型。它将在大多数编译器上工作(请参见此处为什么),但标准禁止它。


Take a note that it is not possible to solve that exercise, because Window_mgr has a member variable of std::vector which argument is an incomplete type. It will work on most compilers (see here why), but the standard prohibits it.

此示例演示如何使类的成员函数friend:

This example demonstrates how to make a member function friend of a class :

#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);
}

这篇关于如何声明两个类,使A有B和B的成员标记A的成员作为朋友?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆