How to declare two classes such that A has members of B and B marks
members of A as friends?
I am attempting to do exercise 7.32 from C++ Primer 5th Edition. That
exercise asks the following:
Define your own versions of Screen and Window_mgr in which clear is a
member of Window_mgr and a friend of Screen.
Here are the definitions for Screen, Window_mgr and clear given in the text.
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, ' ');
}
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.
The text gives the following hints:
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.
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, ' ');
}
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.
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?
No comments:
Post a Comment