typedef std::string::size_type pos;
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
};
Тип pos
определен в части public
класса Screen
, поскольку пользователи должны использовать это имя. Пользователи класса Screen
не обязаны знать, что он использует класс string
для хранения своих данных. Определив тип pos
как открытый член, эту подробность реализации класса Screen можно скрыть.
В объявлении типа pos
есть два интересных момента. Во-первых, хоть здесь и был использован оператор typedef
(см. раздел 2.5.1), с таким же успехом можно использовать псевдоним типа (см. раздел 2.5.1):
class Screen {
public:
//
//
using pos = std::string::size_type;
//
};
Во-вторых, по причинам, которые будут описаны в разделе 7.3.4, в отличие от обычных членов, типы-члены определяются прежде, чем используются. В результате типы-члены обычно располагают в начале класса.
Screen
Чтобы сделать наш класс полезней, добавим в него конструктор, позволяющий пользователям задавать размер и содержимое экрана, наряду с членами, позволяющими переместить курсор и получить символ в указанной позиции:
class Screen {
public:
typedef std::string::size_type pos;
Screen() = default; //
//
//
Screen(pos ht, pos wd, char c) : height(ht), width(wd),
contents(ht * wd, c) { }
char get() const //
{ return contents [cursor]; } //
inline char get(pos ht, pos wd) const; //
Screen &move(pos r, pos с); //
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
};
Поскольку мы предоставляем конструктор, компилятор не будет автоматически создавать стандартный конструктор сам. Если у нашего класса должен быть стандартный конструктор, то придется создать его явно. В данном случае используется синтаксис = default
, чтобы попросить компилятор самому создать определение стандартного конструктора (см. раздел 7.1.4).
Стоит также обратить внимание на то, что второй конструктор (получающий три аргумента) неявно использует внутриклассовый инициализатор для переменной-члена cursor
(см. раздел 7.1.4). Если бы у класса не было внутриклассового инициализатора для переменной-члена cursor
, то мы явно инициализировали бы ее наряду с другими переменными-членами.
У классов зачастую бывают небольшие функции, которые выгодно сделать встраиваемыми. Как уже упоминалось, определенные в классе функции-члены автоматически являются встраиваемыми (inline
) (см. раздел 6.5.2). Таким образом, конструкторы класса Screen
и версия функции get()
, возвращающей обозначенный курсором символ, являются встраиваемыми по умолчанию.
Функцию-член можно объявить встраиваемой явно в ее объявлении в теле класса. В качестве альтернативы функцию можно указать встраиваемой в определении, расположенном вне тела класса:
inline //
Screen &Screen::move(pos r, pos с) {
pos row = r * width; //
cursor = row + с; //
return *this; //
}
char Screen::get(pos r, pos с) const //
{
pos row = r * width; //
return contents[row + с]; //
}