Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
46
Добавлен:
16.04.2013
Размер:
99.33 Кб
Скачать

Конструкторы как преобразования

Конструктор с единственным параметром автоматически является функцией преобразования, если только он не объявлен с ключевым словом explicit. Рассмотрим следующий класс, назначение которого — напечатать невидимые символы с их представлением ASCII; например, код с восьмеричным номером 07 — это звонок (звуковой сигнал).

//Печатаемые символы ASCII

class pr_char { public:

pr_char(int i = 0) : c(i % 128) {}

void print() const { cout <<rep[c];}

private:

int c;

static const char* rep(128];

};

const char* pr_char::rep[128] = { "nul", "soh", "stx",

.......

" w ", " x "," y ", "z ", "{"," | ", " } ", " ~", " de1"};

int main ()

{

pr_char с ;

for (int i = 0; i < 128; ++i) {

с = i; //или: c=static_cast<pr_char>(i)

c.print() ;

cout << endl ;

}

}

Конструктор выполняет автоматическое преобразование типа int в тип pr_char. Отметьте, что инструкция в цикле

c = i;

как раз и заключает в себе это преобразование.

Создание динамического стека

Конструктор можно также использовать для выделения пространства из свободной памяти.

//Реализация ch_stack с конструктором

class ch_stack { public:

//открытый интерфейс для АТД ch_stack

explicit ch_stack(int size) : max_len(size), top(EMPTY)

{ assert(size > 0); s = new char[size]; assert(s != 0);}

void reset () { top = EMPTY; }

void push(char c) { s[++top] = c; }

char pop() { return s[top--]; }

char top_of() const { return s[top]; }

bool empty() const { return (top = = EMPTY); }

bool full() const { return (top = = max_len - 1); }

private:

enum { EMPTY = -1 };

char* s; //было s[max_len]

int max_len;

int top;

};

Теперь клиент, использующий ch_stack, может выбрать требуемый размер. Пример объявления ch_stack с вызовом конструктора выглядит так:

ch_stack data(l000); //размещение 1000 элементов

ch_stack more_data(2 * n) ; //размещение 2*п элементов

Создадим два дополнительных конструктора. Один — с пустым списком параметров, он будет размещать ch_stack определенной длины. Другой — с двумя параметрами, его второй параметр типа char* будет использоваться для инициализации ch_stack. Их можно записать так:

//конструктор по умолчанию для ch_stack

ch_stack::ch_stack() : max_len(100),top(EMPTY)

{

s = new char[100];

assert(s != 0) ;

}

//инициализация стека строкой

ch_stack::ch_stack(int size, const char str[]) : max_len(size)

{

int i;

assert(size > 0);

s = new char[size];

assert(s != 0) ;

for (i = 0; i < max_len && str[i] != 0; ++i)

s[i] = str[i];

top = --i;

}

Соответствующие прототипы функций должны быть включены как члены в класс ch_stack. Используем эти конструкторы следующим образом:

ch_stack data; //создает s[l00]

ch_stack d[N]; //N стеков по 100 элементов

ch_stack w(4, "ABCD"); //w.s[0]='A' ... w.s[3]='D'

Копирующий конструктор

Рассмотрим наш стек и подсчитаем, сколько раз встречается заданный символ. Можно многократно извлекать элементы из стека, проверяя каждый из них по очереди, до тех пор пока стек не будет пуст. Но что если мы хотим сохранить нетронутым содержимое стека? Вызываемые по значению параметры именно это и выполняют:

int cnt_char(char с, ch_stack s)

{

int count = 0;

while (! s.empty())

count += (c = = s.pop());

return count;

}

Семантика вызова по значению требует, чтобы была создана локальная копия аргумента, и чтобы она была инициализована значением выражения, переданного в качестве фактического параметра. Для этого необходим копирующий конструктор (сорy constructor). Компилятор предоставляет копирующий конструктор по умолчанию. Его сигнатура такова:

ch_stack::ch_stack(const ch_stack&);

Компилятор выполняет копирование с помощью почленной инициализации (memberwise initialization). Она может не работать при некоторых обстоятельствах для сложных агрегатов с членами, являющимися указателями.

//Копирующий конструктор для ch_stack из символов

ch_stack::ch_stack(const ch_stack& str) :

max_len(str.max_len), top(str.top)

{

s = new char[str.max_len];

assert(s != 0) ;

memcpy(s, str.s, max_len);

}

Процедура memcpy () из stdlib.h копирует max_len символов начиная с базового адреса str.s в память, начинающуюся с базового адреса s.

Соседние файлы в папке Тельминов (мб)