0

这个问题来自“Thinking in C++” Vol-1,Chapter 5's practice 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");
} ///:~

我想我走错了路,谁能给我一些关于如何解决这个问题的提示?

4

3 回答 3

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 的用户(测试代码)不必重新编译,因为header 中没有任何更改

阅读更多关于作者称之为“柴郡猫”的技术:不透明指针


请注意,我不明白您对 void 指针的用法。StackOfInt 应该接受并返回整数。

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

于 2011-03-23T20:17:16.183 回答
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();
     }
于 2011-03-23T20:16:47.693 回答
0

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

于 2011-03-23T20:10:06.577 回答