我一直在尝试书中的一些例子(Stanley Lippman的C ++ Primer) 我理解一个类可以使另一个类成为它的朋友(访问一些私有成员)。现在我正在阅读一个成员函数作为朋友,我尝试了这个例子
class Screen
{
public:
friend void Window_mgr::clear();
typedef std::string::size_type pos;
Screen () = default;
Screen (pos ht, pos wd, char c) : height (ht), width (wd),
contents (ht * wd, c) { }
private:
void do_display (std::ostream &os) const
{
os << contents;
}
pos cursor = 0;
pos height = 0, width = 0;
pos test_num = 100, test_num2 = 222;;
std::string contents = "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, ' ');
}
但它会产生编译错误
尚未声明Window_mgr
然后我读到了这个:
•首先,定义Window_mgr类,它声明但不能定义清除。必须在clear之前声明屏幕才能使用Screen的成员。
•接下来,定义类屏幕,包括明确的朋友声明。
•最后,明确清楚,现在可以引用屏幕中的成员。
我不明白这一部分 - 有人可以解释一下吗?
答案 0 :(得分:3)
你大部分都在那里,你只需要确保在需要声明之前声明所有的类和函数。
第一个指令点表示定义Window_mgr
类声明Window_mgr::clear
。要使用Screen
,还必须在Window_mgr
之前声明该类。这看起来像:
class Screen; //forward-declare Screen so that Window_mgr knows it exists
class Window_mgr {
public:
//requires forward declaration of Screen, like the above
using ScreenIndex = std::vector<Screen>::size_type;
void clear (ScreenIndex); //declare, but don't define, clear
};
第二点是定义Screen
并包含Window_mgr::clear
的朋友声明。因为上面已经声明了该成员函数,所以这是有效的:
class Screen
{
public:
using ScreenIndex = std::vector<Screen>::size_type;
//remember to friend with the same arguments
friend void Window_mgr::clear(ScreenIndex);
//...
};
最后一点告诉您现在定义Window_mgr::clear
。我们已经在第一点宣布了,所以我们只需要这样做:
void Window_mgr::clear(ScreenIndex i)
{
//...
}
答案 1 :(得分:2)
当编译器到达friend void Window_mgr::clear();
时,它不知道Window_mgr
是什么,因为它还没有看到。你需要重新排序一些东西以使其工作。首先你转发声明Screen
,然后你有Window_mgr
class Screen;
class Window_mgr {
public:
using ScreenIndex = std::vector<Screen>::size_type;
void clear(ScreenIndex);
Window_mgr();
private:
std::vector <Screen> screens; // don't initialize here as we don't know what a screen actually is yet
//std::vector <Screen> screens {Screen (24, 80, ' ')}; can't do this as we don't what a Screen is here
};
然后你可以拥有Screen
课程
class Screen
{
public:
friend void Window_mgr::clear(ScreenIndex);
typedef std::string::size_type pos;
Screen() = default;
Screen(pos ht, pos wd, char c) : height(ht), width(wd),
contents(ht * wd, c) { }
private:
void do_display(std::ostream &os) const
{
os << contents;
}
pos cursor = 0;
pos height = 0, width = 0;
pos test_num = 100, test_num2 = 222;
std::string contents = "contents";
};
然后,您可以使用Window_mgr
Screen
部分
Window_mgr::Window_mgr() : screens{ Screen(24, 80, ' ') } {}
void Window_mgr::clear(ScreenIndex i)
{
Screen &s = screens[i];
s.contents = std::string(s.height * s.width, ' ');
}
您可以在此live example
中查看所有内容答案 2 :(得分:1)
一个问题是clear
方法的签名有所不同。在Screen
类中声明的那个接受一个参数,而另一个没有。签名必须相同,或者语言实际上将它们视为不同的功能。
第二个问题是你的实现与你的第一点冲突:&#34;定义Window_mgr
类,它声明但不能定义clear
。&#34;您的Window_mgr
类都声明并定义clear
。