реализовать IntStack с шаблоном моста в C ++ - PullRequest
0 голосов
/ 23 марта 2011

Этот вопрос был из "Мышление в C ++", том 1, упражнение № 5 главы 5:

Создайте класс StackOfInt (стек, содержащий целые числа), используя Техника «Чеширский кот», которая скрывает низкоуровневую структуру данных используйте для хранения элементов в классе с именем StackImp. Реализовать два версии StackImp: в одной используется массив int фиксированной длины, и тот, который использует вектор. Иметь предустановленный максимальный размер для стека так что вам не нужно беспокоиться о расширении массива в первом версия. Обратите внимание, что класс StackOfInt.h не должен изменяться с StackImp.

Вот заголовочный файл (StackOfInt.h), который я создал:

#ifndef STACKOFINT_H
#define STACKOFINT_H

class StackOfInt
{
    int size;
    int curr_idx;
    class StackImp;
    StackImp* head;
  public:
    void initialize(int max);
    void push(void* dat);
    void* peek();
    void* pop();
    void cleanup();
};
#endif

Однако, для реализации, я запутался в том, как обрабатывать разницу между массивом и вектором. Вот что я придумала до сих пор:

#include "StackOfInt.h"
#include "require.h"
#include <vector>

class StackOfInt::StackImp
{
    int arrInt[50];
  public:
    void initialize()
    {
        for (int i = 0; i < 50; i++)
        {
            arrInt[i] = 0;
        }
    }
};

/*
class StackOfInt::StackImp
{
    std::vector<int> vecInt;
}
*/

void StackOfInt::initialize(int max)
{
    size = max;
    curr_idx = 0;
    head = 0;
    StackImp* newImp = new StackImp;
    newImp->initialize();
}

void StackOfInt::push(void* dat)
{
    *(head+curr_idx) = dat;
    curr_idx++;
}

void* Stack::peek(int idx)
{
    require(head != 0, "Stack empty");
    return head[idx];
}

void Stack::cleanup()
{
    require(head == 0, "Stack not empty");
} ///:~

Я думаю, что я на неправильном пути, может кто-нибудь дать мне несколько советов, как решить эту проблему?

Ответы [ 3 ]

1 голос
/ 23 марта 2011

Автор книги имеет в виду, что класс StackOfInt не должен содержать никаких других членов, кроме указателя на класс реализации.Необходимые члены данных, будь то переменная массива + счетчика или вектор, должны быть членами класса реализации.

Таким образом, в заголовке у вас будет

class StackOfInt {

    class StackImp;
    StackImp* impl;
public:
    void initialize();
    void push(int dat);
    int peek();
    int pop();
    void cleanup();
};

.В файле реализации у вас будет реализация:

class StackOfInt::StackImp
{
public:
    int count;
    int array[100];
};

void StackOfInt::initialize()
{
    impl = new StackImp;
    impl->count = 0;
}

void StackOfInt::push(int dat)
{
    impl->array[impl->count++] = dat;
}

//and other methods

Напишите другой файл cpp, который использует класс StackOfImp.Скомпилируйте проект и запустите программу, чтобы убедиться, что все работает хорошо:)

Теперь вы можете полностью переписать файл реализации для StackOfInt, чтобы использовать вектор в качестве базового типа.Перекомпилируйте проект.Обратите внимание, что пользователь StackOfImp (тестовый код) не должен быть перекомпилирован, потому что ничего не изменилось в заголовке .

Чтобы узнать больше о методике, которую автор называет "Чеширский кот"": Непрозрачный указатель


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

Вызов указателя реализации head также указывает на некоторое недопонимание.Это представляет указатель на объект, который фактически будет содержать необходимые члены для реализации стека.

0 голосов
/ 23 марта 2011

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

StackImplArr.cpp

     class StackOfInt::StackImp
     {
       int arrInt[50];
     }

StackImplVec.cpp

     class StackOfInt::StackImp
     {
       std::vector<int> vecInt;
     }

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

     class StackOfInt::StackImp
     {
       virtual initialize() = 0;
     }

     class StackOfInt::StackImpArr : public StackOfInt::StackImp
     {
       int arrInt[50];
       virtual initialize() { ... }
     }

     class StackOfInt::StackImpVec : public StackOfInt::StackImp
     {
       std::vector<int> vecInt;
       virtual initialize() { ... }
     }

     void
     StackOfInt::initialize( int max) {
       head = condition ? new StackImpArr() : new StackImpVec();
     }
0 голосов
/ 23 марта 2011

Один из способов обработки - сделать полиморфный класс «impl» и использовать фабрику для выбора реализации во время построения.

...