练习7.23 & 7.24 编写你的自己的Screen类。给你的Screen类添加三个构造函数:一个默认构造函数;另一个构造函数接受宽和高的值,然后将contents初始化成给定数量的空白;第三个构造函数接受宽和高的值以及一个字符,该字符作为初始化之后屏幕的内容。
#include <string>
class Screen
{
public:
typedef std::string::size_type pos;
Screen() = default;
Screen(pos ht, pos wd) :height(ht), width(wd) {}
Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c) {}
char get()const { return contents[cursor]; }
char get(pos ht, pos wd)const { pos row = ht*width; return contents[row + wd]; }
Screen &move(pos, pos);
private:
pos cursor = 0;
pos height = 0;
pos width = 0;
std::string contents;
};
inline
Screen& Screen::move(pos r, pos c)
{
pos row = r*width;
cursor = row + c;
return *this;
}
练习7.25 Screen能安全地依赖于拷贝和和赋值操作的默认版本吗?请说明理由。
不可以。
Screen myScreen(7, 77, 'n');//正确的一种初始化。n是char类型。
//错误,以下数据成员被定义为私有类型。
myScreen.width = 7;
myScreen.height = 77;
myScreen.cursor = 7777;
myScreen.contens = "nnnnnnnnnnnn";
练习7.26 将Sales_data::avg_price定义成内联函数。
三种将类成员函数定义成内联函数的方法。
1.隐式内联函数,定义在类内的成员函数。
2.显式内联函数,定义在类内的有inline标识符的成员函数。
3.显式内联函数,定义不在类内的成员函数,此时的inline是必须的。
练习7.27 给你自己的Screen类添加move、set、和display函数,通过执行下面的代码检验你的类是否正确。
#include <string>
class Screen
{
public:
typedef std::string::size_type pos;
Screen() = default;
Screen(pos ht, pos wd) :height(ht), width(wd) {}
Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c) {}
char get()const { return contents[cursor]; }
char get(pos ht, pos wd)const { pos row = ht*width; return contents[row + wd]; }
Screen &move(pos, pos);
Screen &set(char);
Screen &set(pos, pos, char);
Screen &display(std::ostream &os) { do_display(os); return *this; }
const Screen &display(std::ostream &os) const { do_display(os); return *this; }
private:
pos cursor = 0;
pos height = 0;
pos width = 0;
std::string contents;
void do_display(std::ostream &os) const { os << contents; }
};
Screen &Screen::set(char c)
{
contents[cursor] = c;
return *this;
}
Screen &Screen::set(pos r, pos c, char ch)
{
contents[r*width + c] = ch;
return *this;
}
inline
Screen& Screen::move(pos r, pos c)
{
pos row = r*width;
cursor = row + c;
return *this;
}
练习7.28 如果move、set和display函数的返回类型不是Screen&而是Screen,则在上一个练习中将会发生什么情况。
如果返回类型不是对象的引用,而是对象的副本。
那么屏幕上第一行输出的是myScreen设置后的内容。
而第二行输出的是myScreen初始化的内容。
练习7.29 修改你的Screen类,令move、set和display函数返回screen并检查程序的运行结构,在上一个练习中你的推测正确吗?
。。。
练习7.30 通过this指针使用成员的做法虽然合法,但是有点多余。讨论显式地使用指针访问成员的优缺点。
(来源网上)
一般使用this指针都是类的成员函数,可以对类中的成员随意访问。
优点:this指针自动感应定位类成员。
缺点:使所有成员都用this看起来一致(有点牵强吧。。。)
练习7.31 定义一对类X和Y,其中X包含一个指向Y的指针,而Y包含一个类型为X的对象。
class X;
class Y;
class X {
Y * ptr;
};
class Y {
X item;
};
练习7.32 定义你自己的Screen和Window_mgr,其中clear是Window_mgr的成员,是Screende的友元。
#include <string>
#include <vector>
class Window_mgr
{
public:
typedef std::string::size_type ScreenIndex;
Window_mgr() = default;
void clear(ScreenIndex);
private:
std::vector<Screen> screens{ Screen{24,80,' '} };
};
class Screen
{
<pre name="code" class="cpp"> friend class Window_mgr;// 友元
public://...private://...};//成员函数的定义// 将celar()函数定义在Screen之后void Window_mgr::clear(ScreenIndex i){Screen &s = screens[i];s.contents = string(s.width*s.height, ' ');}