Screen类实现:
#pragma once
#include<string>
#include<iostream>
class Screen {
friend class Windows_mgr;//类也可以被定义为友元
public:
//用于定义类型的成员必须先定义后使用
typedef std::string::size_type pos; //string::size_type类型与unsigned具有相同含义,其长度与实际机器适配,是string类定义的配套类型,例如size()的返回类型就是size_type类型
//using pos = std::string::size_type; 别名声明,与typedef等价
/*构造函数*/
explicit //阻止了隐式通过该构造函数创建对象
Screen(pos ht,pos wd,char c):height(ht),width(wd), //最好初始值顺序与声明保持一致,也尽量避免使用某些成员初始化其他成员
contents(ht * wd, c) { } //cursor被类内初始值初始化为0
Screen(): Screen(0, 0, ' ') { } //委托构造函数,使用所属类其他构造函数执行自己的初始化过程
/*类内成员函数*/
//获取位置和移动
char get() const //隐式内联
{ return contents[cursor]; } //读取光标处字符
inline char get(pos ht, pos wd) const; //显式内联
Screen& move(pos r, pos c); //定义时设为内联
//设置光标位置
Screen& set(char); //返回*this的成员函数,于是我们就可以这样用:myScreen.move(4,0).set('#')
Screen& set(pos, pos, char); //上面表达正确是由于我们返回的是myScreen的别名,而不是副本
//display方法
//一个const成员函数如果以引用的形式返回*this,那么它的返回类型将是常量引用
Screen &display(std::ostream &os)
{ do_display(os); return *this; } //于是我们可以使用myScreen.display(cout).set('*'),并且负责打印的函数是const函数
const Screen& display(std::ostream& os) const
{ do_display(os); return *this; }
Screen& clear(char = bkground); //使用静态成员作为静态实参
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
//静态成员
static const char bkground;
/*类内成员函数*/
void do_display(std::ostream& os) const { os << contents; } //是内联函数,不会产生额外开销,同时又保证了设计的优良性
};
/*类外定义成员函数*/
inline //能在外部用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;
}
Windows_mgr类实现:
#pragma once
#include"Screen.h"
#include<vector>
/*令某个成员函数作为友元,设计程序流程如下:
* 1、首先定义Window_mgr类,其中声明clear函数,但是不能定义它;
* 在使用Screen的成员前必须先声明Screen;
* 2、接下来定义Screen,包括对于clear的友元声明
* 3、最后定义clear,此时它才可以使用Screen的成员
*/
class Windows_mgr {
public:
using ScreenIndex = std::vector<Screen>::size_type; //vector定义的size_type类型与string一致,unsigned,注意:作用域只在类内
//按照编号将特定Screen重置为空白
void clear(ScreenIndex);
//向窗口添加一个Screen,返回编号
ScreenIndex addScreen(const Screen&);
private:
//这个Windows_mgr追踪的Screen
//默认情况下。一个Window_mgr包含一个标准尺寸的空白Screen
std::vector<Screen> screens{ Screen(24,80,' ') };//当提供一个类内初始值是,必须以符号=或者花括号表示
};
void Windows_mgr::clear(ScreenIndex i) {
Screen& s = screens[i];
s.contents = std::string(s.height * s.width, ' ');
}
Windows_mgr::ScreenIndex //返回类型出现在函数名之前,其定义在类的作用域内,使用在作用域之外,所以必须指明是哪个类定义了它
Windows_mgr::addScreen(const Screen& s) {
screens.push_back(s); //vector容器的动态长度
return screens.size() - 1;
}