class Window_mgr;
class Screen
{
friend class Window_mgr;
public:
using pos = string::size_type;
//下面三个构造函数 隐式内联
Screen() = default;
Screen(pos he, pos wi) :height(he), width(wi), contents(he* wi, ' ') {}
Screen(pos he, pos wi, char c) :height(he), width(wi), contents(he* wi, c) {}
char get() const { return contents[cursor]; } //隐式内联
char get(pos, pos) const; //显示内联 一般推荐在类外定义处标明inline
Screen& move(pos, pos);
Screen& set(pos, pos, char);
Screen& set(char);
// 此处对于display函数进行基于const的重载原因是:display函数本身应该定义为const的,因为它不会对调用它的对象进行修改,但是返回值是引用类型的,若一个普通对象调用display函数,则返回const Screen&
// 这时就不合适了,因为例如s.display().move(3,3).get();这样的操作就非法了。所以对于display函数再进行基于const的重载,使非常量对象调用非常量版本的display函数,是合适的。
const Screen& display()const;
Screen& display();
private:
void do_display() const { cout << contents; };
pos cursor = 0;
pos height = 0, width = 0;
string contents;
};
inline const Screen& Screen::display()const
{
do_display();
return *this; //此处this指向一个const类型的对象,你返回之后没有了const 当然不行!!!
}
inline Screen& Screen::display()
{
do_display();
return *this;
}
inline Screen& Screen::set(pos r, pos c, char ch)
{
contents[r * width + c] = ch;
return *this;
}
inline Screen& Screen::set(char c)
{
contents[cursor] = c;
return *this;
}
inline char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
inline Screen& Screen::move(pos r, pos c)
{
pos row = r * width;
cursor = row + c;
return *this;
}
class Window_mgr
{
public:
using ScreenIndex = vector<Screen>::size_type;
void clear(ScreenIndex);
ScreenIndex addScreen(const Screen&);
private:
vector<Screen> screens{ Screen(3,3,'*') };
};
void Window_mgr::clear(ScreenIndex n)
{
Screen& s = screens[n];
s.contents = string(s.height * s.width, ' ');
}
Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen& s)
{
screens.push_back(s);
return screens.size() - 1;
}
1. 某些函数为什么要定义为const型函数
如果是一个常量对象即const型对象调用某非const函数,前提是此函数不会对对象的数据成员进行修改,则此对象调用这个函数之后,这个函数内部的this指针是一个指向非常量对象的针, 即type * const this类型指针(this指针永远是一个常量指针,即指针指向不可变),显然,将一个常量对象的地址赋予一个普通的指针是非法的,所以对于那些不会改变数据成员的函数,设定为const类型,可以使该函数内部的this指针变为指向const类型对象的指针,这样,常量对象也就可以合法地使用该函数了,不过说实话,我觉得创建const对象的机会还是比较少的。(真的很啰嗦)。(刚刚实践了一下,即使某类的数据成员是public的,仍不可以修改该类的const对象的public成员。)
2. 对于display函数进行基于const的重载的原因
此处对于display函数进行基于const的重载原因是:display函数本身应该定义为const的,因为它不会对调用它的对象进行修改,但是返回值是引用类型的,若一个普通对象调用display函数,则返回const Screen&,这时就不合适了,因为例如s.display().move(3,3).get();这样的操作就非法了。所以对于display函数再进行基于const的重载,使非const对象调用非const版本的display函数,是合适的。
但是,如果该函数返回值不是一个引用类型的话,还有必要定义非const版本的display函数吗。其实也就没什么必要了。不过这个函数就是要返回引用类型,因为这样是更合适的。
3. 若某构造函数,没有给某数据成员赋值,且该数据成员没有类内初始值,是可以的,只是这种内置类型的数据成员值为随机值,且因为一般情况下,数据成员都是private的,很难修改,所以。若某构造函数没给某数据成员赋值,则该数据成员应当有类内初始值。 参数初始化列表进行的操作是初始化,构造函数体的作用是赋值。所以引用等类型也就必须进行初始化了,这是能想到的认为比较重要的知识点吧