C++ Primer 第七章 Screen类与Window_mgr类

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::size_type;
	void clear(ScreenIndex);
	ScreenIndex addScreen(const Screen&);
private:
	vector 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的,很难修改,所以。若某构造函数没给某数据成员赋值,则该数据成员应当有类内初始值。 参数初始化列表进行的操作是初始化,构造函数体的作用是赋值。所以引用等类型也就必须进行初始化了,这是能想到的认为比较重要的知识点吧

你可能感兴趣的:(c++primer,c++,开发语言)