一个类的成员函数作为另一个类的友元,该成员函数就必须在另一个类之前被声明。又因为类的成员函数必须在类内被声明,因此,两个类的顺序被固定。
Window_mgr类中的clear作为Screen的友元。遵循步骤:
需要先定义Window_mgr类;
声明clear函数,但不能定义,因为Screen还没有定义,不能使用Screen类。
定义Screen类
在类外定义clear。
typedef string::size_type screenindex;
class Window_mgr {
public:
void clear(screenindex i);
private:
vector<Screen> screens{ Screen(24,80,'a') };
};
class Screen {
friend void Window_mgr::clear(screenindex i);
public:
//pos
typedef string::size_type pos;
//构造函数
Screen() = default;
//接受高、宽、字符三个量来创建窗口。
Screen(pos ht, pos wd, char c) :height(ht),width(wd),
contents(ht*wd,c){}
//接受高、宽两个参数来创建空白窗口
Screen(pos ht, pos wd) :height(ht), width(wd),
contents(ht*wd,' ') {}
Screen& set(char);
Screen& set(pos, pos, char);
char get() const
{
return contents[cursor];
}
inline char get(pos ht, pos wd) const;
Screen& move(pos r, pos c);
Screen& display(ostream &os) {
do_display(os); return *this;
}
const Screen& display(ostream& os) const {//后一个const说明了函数内部不改变成员变量,这是一个const成员函数
//const对象只能调用const成员函数
//前一个const 是因为后一个const将this变成一个指向const的cosnt指针。
do_display(os); return *this;
}
private:
pos cursor = 0;
pos height = 0, width = 0;
string contents;
void do_display(ostream& os) const {
for (pos i = 0; i < width * height; ++i)
{
if (i % width == 0) cout << endl;
cout << contents[i];
}
}
};
inline
Screen& Screen::move(pos r, pos c) {
pos row = r * width;
cursor = row + c;
return *this;
}
char Screen::get(pos r, pos c) const {
pos row = r * width;
return contents[row + c];
}
inline Screen& Screen::set(char c) {
contents[cursor] = c;
return *this;
}
inline Screen& Screen::set(pos r, pos col, char ch) {
contents[r * width + col] = ch;
return *this;
}
void Window_mgr::clear(screenindex i) {
Screen& s = screens[i];
s.contents = string(s.width*s.height,' ');
}
这样的定义使得clear成员函数变成Screen的友元,但是该代码的Window_mgr类中的成员vector screens定义是错误的,要先定义Screen类,才能将Screen作为vector的类型。
这样clear和screens就有冲突。将Window_mgr类整体设置为Screen的友元,冲突取消。
class Screen {
friend class Window_mgr;
public:
//pos
typedef string::size_type pos;
//构造函数
Screen() = default;
//接受高、宽、字符三个量来创建窗口。
Screen(pos ht, pos wd, char c) :height(ht),width(wd),
contents(ht*wd,c){}
//接受高、宽两个参数来创建空白窗口
Screen(pos ht, pos wd) :height(ht), width(wd),
contents(ht*wd,' ') {}
Screen& set(char);
Screen& set(pos, pos, char);
char get() const
{
return contents[cursor];
}
inline char get(pos ht, pos wd) const;
Screen& move(pos r, pos c);
Screen& display(ostream &os) {
do_display(os); return *this;
}
const Screen& display(ostream& os) const {//后一个const说明了函数内部不改变成员变量,这是一个const成员函数
//const对象只能调用const成员函数
//前一个const 是因为后一个const将this变成一个指向const的cosnt指针。
do_display(os); return *this;
}
private:
pos cursor = 0;
pos height = 0, width = 0;
string contents;
void do_display(ostream& os) const {
for (pos i = 0; i < width * height; ++i)
{
if (i % width == 0) cout << endl;
cout << contents[i];
}
}
};
class Window_mgr {
public:
Window_mgr& clear(screenindex i);
Window_mgr& print(screenindex i);
private:
vector<Screen> screens{ Screen(24,80,'a') };
};
inline
Screen& Screen::move(pos r, pos c) {
pos row = r * width;
cursor = row + c;
return *this;
}
char Screen::get(pos r, pos c) const {
pos row = r * width;
return contents[row + c];
}
inline Screen& Screen::set(char c) {
contents[cursor] = c;
return *this;
}
inline Screen& Screen::set(pos r, pos col, char ch) {
contents[r * width + col] = ch;
return *this;
}
Window_mgr& Window_mgr::clear(screenindex i) {
Screen& s = screens[i];
s.contents = string(s.width * s.height, ' ');
return *this;
}
Window_mgr& Window_mgr::print(screenindex i) {
Screen& s = screens[i];
s.display(cout);
return *this;
}