【发布时间】:2013-09-19 21:19:21
【问题描述】:
我正在尝试做 C++ Primer 5th Edition 中的练习 7.32。该练习提出以下问题:
定义您自己的
Screen和Window_mgr版本,其中clear是Window_mgr的成员和Screen的朋友。
以下是文中给出的Screen、Window_mgr 和clear 的定义。
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。要让clear成为会员,如果我理解正确的话,Window_mgr必须被定义。要定义Window_mgr,必须定义Screen。这对我来说似乎是不可能的。
文字给出了以下提示:
使成员函数成为朋友需要仔细构造我们的程序以适应声明和定义之间的相互依赖关系。在这个例子中,我们必须按如下顺序排列我们的程序:
首先,定义
Window_mgr类,它声明但不定义clear。Screen必须在clear可以使用Screen的成员之前声明。接下来,定义类
Screen,包括clear的朋友声明。最后,定义
clear,现在可以引用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 中的向量需要Screen 是一个完整的类型。这似乎是一个无法解决的问题,除非作者不打算使用他们之前介绍的 Screen 和 Window_mgr 类。
有没有其他人从 C++ Primer 中解决了这个练习。如果是这样,怎么做?任何帮助如何做到这一点,或者正如我的直觉告诉我的那样,无法做到?
【问题讨论】:
-
"首先,定义
Window_mgr类 [...] 接下来,定义Screen" 听起来Window_mgr不应有(非指针非引用)类型的成员Screen(或者,在这种情况下为std::vector<Screen>)。 -
是的,我也是这么想的,但显然他们对
clear的定义使用了他们在Window_mgr中定义的向量。这似乎真的是一个经过深思熟虑的练习。 -
我认为使用
std::shared_ptr<Screen>向量是不可能的,嗯。 -
即使使用
std::shared_ptr<Screen>,作者设计的Window_mgr类也会使用默认屏幕初始化向量,并且需要定义一个非默认构造函数,不是吗? -
@Adam 你可以定义自己的默认构造函数,但是你必须自己定义,在
Screen的定义之后。
标签: c++ class friend forward-declaration