会员功能朋友
Member function a friend
我一直在尝试书中的一些示例(Stanley Lippman 的 C++ Primer)
我知道 class 可以让另一个 class 成为朋友(访问一些私有成员)。现在我正在阅读有关成员函数成为朋友的信息,我尝试了示例
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 has not been declared
然后我读了这个:
• First, define the Window_mgr class, which declares, but cannot define, clear. Screen must be declared before clear can use the members of Screen.
• Next, define class Screen, including a friend declaration for clear.
• Finally, define clear, which can now refer to the members in Screen.
我不明白这部分 -- 谁能解释一下?
您已经完成了大部分工作,您只需要确保在需要声明之前声明所有 classes 和函数。
第一个指令点说定义 Window_mgr
class 声明 Window_mgr::clear
。为了使用 Screen
,class 也必须在 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)
{
//...
}
一个问题是您的 clear
方法的签名不同。在 Screen
class 中声明的一个带参数,另一个不带参数。签名必须相同,否则语言实际上将它们视为不同的函数。
第二个问题是您的实现与第一点冲突:"define the Window_mgr
class, which declares, but cannot define, clear
." 您的 Window_mgr
class 既声明又定义了 clear
。
当编译器到达 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
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
我一直在尝试书中的一些示例(Stanley Lippman 的 C++ Primer) 我知道 class 可以让另一个 class 成为朋友(访问一些私有成员)。现在我正在阅读有关成员函数成为朋友的信息,我尝试了示例
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 has not been declared
然后我读了这个:
• First, define the Window_mgr class, which declares, but cannot define, clear. Screen must be declared before clear can use the members of Screen.
• Next, define class Screen, including a friend declaration for clear.
• Finally, define clear, which can now refer to the members in Screen.
我不明白这部分 -- 谁能解释一下?
您已经完成了大部分工作,您只需要确保在需要声明之前声明所有 classes 和函数。
第一个指令点说定义 Window_mgr
class 声明 Window_mgr::clear
。为了使用 Screen
,class 也必须在 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)
{
//...
}
一个问题是您的 clear
方法的签名不同。在 Screen
class 中声明的一个带参数,另一个不带参数。签名必须相同,否则语言实际上将它们视为不同的函数。
第二个问题是您的实现与第一点冲突:"define the Window_mgr
class, which declares, but cannot define, clear
." 您的 Window_mgr
class 既声明又定义了 clear
。
当编译器到达 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
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