Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Практическая разработка средств объектно-ориентированного программирования в задачах защиты информации




Программная реализация стека на языке С++

 

В случае использования механизмов языка C, стратегия может быть следующей - мы объявляем набор операций для работы со стеком и заводим некоторую структуру для хранения его содержимого. Ниже приведен пример заголовочного файла для стека, а также файл модуля, где реализованы функции работы со стеком, объявленные в заголовке.

 

/* file simple_stack.h 7

#ifndef _SIMPLE_STACK_H

#define _SIMPLE_STACK_H

#define MAX_STACK_SIZE 200

 

typedef struct {top;* content [MAX_STACK_SIZE];

} SimpleStack;

 

/* returns -1 if overflow 7push (SimpleStack *pstack, void *pobj);

/* returns NULL if empty 7* pop (SimpleStack *pstack);

* allocateStack();freeStack (SimpleStack *pstack);

#endif/*_SIMPLE_STACK_H */


/* file simple_stack.c */

#include <malloc.h>

#include <stdlib.h>

#include «simple_stack.h»

* allocateStack()

{* pstack =

(SimpleStack*) malloc (sizeof (SimpleStack));>top = 0;pstack;

}

freeStack (SimpleStack *pstack)

{(pstack);

}

push (SimpleStack *pstack, void *pobj)

{(pstack->top < MAX_STACK_SIZE) {>content[(pstack->top)++] = pobj;0;

} else {-1; /* overflow */

}

}

* pop (SimpleStack *pstack)

{(pstack->top > 0) {pstack->content[- (pstack->top)];

} else {

return NULL; /* underflow */

}

}

 

Данная реализация имеет множество недостатков, хотя и может сгодиться для небольших программ. Главными являются следующие два:

Данные экземпляров структуры не защищены от недобросовестного использования. Следующий код может непоправимо нарушить работу программы:

 

SimpleStack pStack = allocateStack();

pStack->top = -10;

 

Стек реализован в виде массива, и нет простого способа заменить его реализацию в программах, уже использующих данную версию.

Мы можем существенно усовершенствовать наш стек, если воспользуемся средствами модульного программирования, имеющимися в языке С++.

 

// Файл advanced_stack.h

// Усовершенствованный вариант стека, использующий

// механизм модульности языка C++

#ifndef _ADVANCED_STACK_H

#define _ADVANCED_STACK_H

 

 // Таким образом мы определяем функциональный

 // контракт модульной реализации стека

namespace advanced_stack {

struct Stack_impl;struct Stack_impl AdvancedStack;

 

// returns -1 if overflowpush (AdvancedStack *pstack, void *pobj);

// returns NULL if empty* pop (AdvancedStack *pstack);

* allocateStack();freeStack (AdvancedStack* pstack);

}

#endif // _ADVANCED_STACK_H

 

// Файл advanced_stack.cpp

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

#include «advanced_stack.h»

 

namespace advanced_stack

{int MAX_STACK_SIZE = 200;Stack_impl {top;* content [MAX_STACK_SIZE];

};

_impl* allocateStack()

{_impl *pstack = new Stack_impl();>top = 0;pstack;

}

freeStack (Stack_impl *pstack)

{pstack;

}

push (Stack_impl *pstack, void *pobj)

{(pstack->top < MAX_STACK_SIZE) {>content[(pstack->top)++] = pobj;0;

} else {-1; // overflow

}

}

* pop (Stack_impl *pstack)

{(pstack->top > 0) {pstack->content[- (pstack->top)];

} else {

return 0; //underflow

}

}

}

 


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

 

#include <stdio.h>

#include «advanced_stack.h»

main()

{namespace advanced_stack;*pstack = allocateStack();

//pstack->top = 10; // Данная строка вызвала бы ошибку компиляции,*letters [3] = {«one», «two», «three»}; int i;(pstack, (void*) (letters[0]));(pstack, (void*) (letters[1]));(pstack, (void*) (letters[2]));(i = 0; i < 3; i++) {(«\n % s\n», (char*) pop(pstack));

}

freeStack(pstack);

}

 

Если в будущем потребуется заменить реализацию стека, то это можно сделать изменив реализацию структуры Stack_impl и функции работы с ней, реализованные в файле advanced_stack.cpp. Также можно объявить новое пространство имен (namespace), например dynamic_stack например, в котором будет реализован стек изменяемого размера. В прежней программе, использующей модульную реализацию стека, достаточно будет заменить строку


using namespace advanced_stack;

на строку namespace dynamic_stack;

 

Это можно сделать при условии, что новое пространство имен имеет контракт, совпадающий с предыдущим.

Таким образом, мы вплотную подошли к идее объединения данных и кода, предназначенного для обработки этих данных, в одну концептуально целостную единицу. Следующим шагом является объектная реализация стека.

 

 // Файл object_stack.h

#ifndef _OBJECT_STACK_H

#define _OBJECT_STACK_H

 

// Объектная модель стека class

ObjectStack

{:const int MAX_STACK_SIZE;top;**content;:

// Вместо allocateStack(…), используется конструктор ObjectStack();

// Вместо freeStack() используется деструктор ~ObjectStack(); int push (void* pobj);

void* pop();

};

 

#endif // _OBJECT_STACK_H


 // Файл object_stack.cpp

#include «object_stack.h»

 

// Реализация объектной модели стекаint ObjectStack:MAX_STACK_SIZE = 200;

: ObjectStack()

:top(0)

{= new void*[MAX_STACK_SIZE];

}

:~ObjectStack()

{[] content;

}

* ObjectStack:pop()

{(top > 0) {content[-top];

} else {0; // underflow

}

}

ObjectStack:push (void* pobj)

{(top < MAX_STACK_SIZE) {[top++] = pobj;0;

} else { -1; // overflow

}

}

 

Примером использования такого стека может служить следующая программа:

 

int main()

{*pstack = new ObjectStack();*letters [3]= {«one», «two», «three»}; int i;

// Доступ к членам данным в принципе невозможен извне

 // функций-членов класса ObjectStack

// pstack->top = -10; // Ошибка времени компиляции

 

pstack->push ((void*) letters[0]);>push ((void*) letters[1]);>push ((void*) letters[2]);(i= 0; i<3; i++) {(«\n % s\n», (char*) pstack->pop());

}

delete pstack;

}

 

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

 


Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...