Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Си++ для начинающих С.Липпман.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
5.71 Mб
Скачать

4.14.4. Устаревшая форма явного преобразования

Операторы явного преобразования типов, представленные в предыдущем разделе, появились только в стандарте С++; раньше использовалась форма, теперь считающаяся устаревшей. Хотя стандарт допускает и эту форму, мы настоятельно не рекомендуем ею пользоваться. (Только если ваш компилятор не поддерживает новый вариант.)

Устаревшая форма явного преобразования имеет два вида:

// появившийся в C++ вид

type (expr);

// вид, существовавший в C


(type) expr;

и может применяться вместо операторов static_cast, const_cast и reinterpret_cast.

Вот несколько примеров такого использования:

const char *pc = (const char*) pcom;

int ival = (int) 3.14159;

extern char *rewrite_str( char* );

char *pc2 = rewrite_str( (char*) pc );


int addr_va1ue = int( &iva1 );

Эта форма сохранена в стандарте С++ только для обеспечения обратной совместимости с программами, написанными для С и предыдущих версий С++.

Упражнение 4.21

Даны определения переменных:

char cval; int ival;

float fval; double dva1;


unsigned int ui;

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

(a) cva1 = 'a' + 3;

(b) fval = ui - ival * 1.0;

(c) dva1 = ui * fval;


(d) cva1 = ival + fvat + dva1;

Упражнение 4.22

Даны определения переменных:

void *pv; int ival;

char *pc; double dval;


const string *ps;

Перепишите следующие выражения, используя операторы явного преобразования типов:

(a) pv = (void*)ps;

(b) ival = int( *pc );

(c) pv = &dva1;


(d) pc = (char*) pv;

4.15. Пример: реализация класса Stack

Описывая операции инкремента и декремента, для иллюстрации применения их префиксной и постфиксной формы мы ввели понятие стека. Данная глава завершается примером реализации класса iStack – стека, позволяющего хранить элементы типа int.

Как уже было сказано, с этой структурой возможны две основные операции – поместить элемент (push) и извлечь (pop) его. Другие операции позволяют получить информацию о текущем состоянии стека – пуст он (empty()) или полон (full()), сколько элементов в нем содержится (size()). Для начала наш стек будет предназначен лишь для элементов типа int. Вот объявление нашего класса:

#include <vector>

class iStack {

public:

iStack( int capacity )

: _stack( capacity ), _top( 0 ) {}

bool pop( int &va1ue );

boot push( int value );

bool full();

bool empty();

void display();

int size();

private:

int _top;

vector< int > _stack;


};

В данном случае мы используем вектор фиксированного размера: для иллюстрации использования префиксных и постфиксных операций инкремента и декремента этого достаточно. (В главе 6 мы модифицируем наш стек, придав ему возможность динамически меняться.)

Элементы стека хранятся в векторе _stack. Переменная _top содержит индекс первой свободной ячейки стека. Этот индекс одновременно представляет количество заполненных ячеек. Отсюда реализация функции size(): она должна просто возвращать текущее значение _top.

inline int iStack::size() { return _top; };

empty() возвращает true, если _top равняется 0; full() возвращает true, если _top равен _stack.size()-1 (напомним, что индексация вектора начинается с 0, поэтому мы должны вычесть 1).

inline bool iStack::empty() { return _top ? false : true; }

inline bool iStack::full() {

return _top < _stack.size()-l ? false : true;


}

Вот реализация функций pop() и push(). Мы добавили операторы вывода в каждую из них, чтобы следить за ходом выполнения:

bool iStack::pop( int &top_va1ue ) {

if ( empty() )

return false;

top_value = _stack[ --_top ];

cout << "iStack::pop(): " << top_value << endl;

return true;

}

bool iStack::push( int value ) {

cout << "iStack::push( " << value << " )\n";

if ( full() )

return false;

_stack[ _top++ ] = value;

return true;


}

Прежде чем протестировать наш стек на примере, добавим функцию display(), которая позволит напечатать его содержимое. Для пустого стека она выведет:

( 0 )

Для стека из четырех элементов – 0, 1, 2 и 3 – результатом функции display() будет:

( 4 )( bot: 0 1 2 3 :top )

Вот реализация функции display():

void iStack::display() {

cout << "( " << size() << " )( bot: ";

for ( int ix = 0; ix < _top; ++ix )

cout << _stack[ ix ] << " ";

cout << " :top )\n";


}

А вот небольшая программа для проверки нашего стека. Цикл for выполняется 50 раз. Четное значение (2, 4, 6, 8 и т.д.) помещается в стек. На каждой итерации, кратной 5 (5, 10, 15...), распечатывается текущее содержимое стека. На итерациях, кратных 10 (10, 20, 30...), из стека извлекаются два элемента и его содержимое распечатывается еще раз.

#inc1ude <iostream>

#inc1ude "iStack.h"

int main() {

iStack stack( 32 ) ;

stack.display();

for ( int ix = 1; ix < 51; ++ix )

{

if ( ix%2 == 0 )

stack.push( ix );

if ( ix%5 == 0 )

stack.display();

if ( ix%10 == 0 ) {

int dummy;

stack.pop( dummy ); stack.pop( dummy );

stack.display();

}


}

Вот результат работы программы:

( 0 )( bot: :top )

iStack push( 2 )

iStack push( 4 )

( 2 )( bot: 2 4 :top )

iStack push( 6 )

iStack push( 8 )

iStack push ( 10 )

( 5 )( bot: 2 4 6 8 10 :top )

iStack pop(): 10

iStack pop(): 8

( 3 )( bot: 2 4 6 :top )

iStack push( 12 )

iStack push( 14 )

( 5 )( bot: 2 4 6 12 14 :top )

iStack::push( 16 )

iStack::push( 18 )

iStack::push( 20 )

( 8 )( bot: 2 4 6 12 14 16 18 20 :top )

iStack::pop(): 20

iStack::pop(): 18

( 6 )( bot: 2 4 6 12 14 16 :top )

iStack::push( 22 )

iStack::push( 24 )

( 8 )( bot: 2 4 6 12 14 16 22 24 :top )

iStack::push( 26 )

iStack::push( 28 )

iStack::push( 30 )

( 11 )( bot: 2 4 6 12 14 16 22 24 26 28 30 :top )

iStack::pop(): 30

iStack::pop(): 28

( 9 )( bot: 2 4 6 12 14 16 22 24 26 :top )

iStack::push( 32 )

iStack::push( 34 )

( 11 )( bot: 2 4 6 12 14 16 22 24 26 32 34 :top )

iStack::push( 36 )

iStack::push( 38 )

iStack::push( 40 )

( 14 )( bot: 2 4 6 12 14 16 22 24 26 32 34 36 38 40 :top )

iStack::рор(): 40

iStack::popQ: 38

( 12 )( bot: 2 4 6 12 14 16 22 24 26 32 34 36 :top )

iStack::push( 42 )

iStack::push( 44 )

( 14 )( bot: 2 4 6 12 14 16 22 24 26 32 34 36 42 44 :top )

iStack::push( 46 )

iStack::push( 48 )

iStack::push( 50 )

( 17 )( bot: 2 4 6 12 14 16 22 24 26 32 34 36 42 44 46 48 50 :top )

iStack::pop(): 50

iStack::pop(): 48

( 15 )( bot: 2 4 6 12 14 16 22 24 26 32 34 36 42 44 46 :top )

Упражнение 4.23

Иногда требуется операция peek(), которая возвращает значение элемента на вершине стека без извлечения самого элемента. Реализуйте функцию peek() и добавьте к программе main() проверку работоспособности этой функции.

Упражнение 4.24

В чем вы видите два основных недостатка реализации класса iStack? Как их можно исправить?