在C ++中实现具有桥接模式的IntStack

时间:2011-03-23 19:55:10

标签: c++ design-patterns stack bridge

这个问题来自“Thinking in C ++”Vol-1,第5章练习No.14:

  

使用。创建一个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 个答案:

答案 0 :(得分:1)

本书作者的想法是,除了指向实现类的指针之外,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

编写另一个使用StackOfImp类的cpp文件。编译项目并运行程序以确保一切正常:)

现在,您可以完全重写StackOfInt的实现文件,以使用向量作为基础类型。重新编译项目。请注意,StackOfImp的用户(测试代码)不必重新编译,因为标题中没有更改

要详细了解作者称之为“柴郡猫”的技术:Opaque pointer


请注意,我不了解您对void指针的使用。 StackOfInt应该采用并返回整数。

调用实现指针head似乎也表明存在一些误解。这表示一个指向实际包含实现堆栈所需成员的对象的指针。

答案 1 :(得分:0)

处理的一种方法是使“impl”类具有多态性并使用工厂在构造时选择实现。

答案 2 :(得分:0)

我认为期望您在两个单独的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();
     }