这个问题来自“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");
} ///:~
我认为我走错了路,有人能给我一些关于如何解决这个问题的提示吗?
答案 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();
}