template<class T>
class Stack
{
public:
Stack();
~Stack();
Stack(const Stack& other);
Stack& operator=(const Stack& other);
size_t Count() const;
void Push(const T&);
// T* Pop();
void Pop();
T* Top() const; // think about it again.
bool Empty() const;
private:
T* v_;
size_t vsize_;
size_t vused_;
};
template<class T>
Stack<T>::Stack() : v_(0), vsize_(10), vused_(0)
{
v_ = new T[vsize_]; //initial allocation, operator new[](), bad_alloc,
}
Stack<T>::Stack() : v_(new T[vsize_]), vsize_(10), vused_(0)
{
}
Stack<T>::~Stack()
{
delete[] v_;
}
template<class T>
T* NewCopy(const T* src, size_t srcsize, size_t destsize)
{
assert(destsize >= srcsize);
T* dest = new T[destsize]; // may throw bad_alloc, or T::T
try
{
copy(src, src+srcsize, dest);
}
catch(...)
{
delete[] dest; // this can't throw
throw; // rethrow original exception
}
return dest;
}
template<class T>
Stack<T>::Stack(const Stack<T>& other): v_(NewCopy( other.v_, other.vsize_, other.vsize_ )),
vsize_(other.vsize_),
vused_(other.vused_)
{
}
template<class T>
Stack<T>& Stack<T>::operator=(const Stack<T>& other)
{
if(this != &other)
{
T* v_new = NewCopy( other.v_, other.vsize_, other.vsize_);
delete[] v_; // this can't throw
v_ = v_new; // take ownership
vsize_ = other.vsize_;
vused_ = other.vused_;
}
return *this; // safe, no copy involved
}
template<class T>
size_t Stack<T>::Count() const
{
return vused_;
}
template<class T>
void Stack<T>::Push(const T& other)
{
if (vused_ == vsize_)
{
size_t vsize_new = vsize_ * 2 + 1;
T* v_new = NewCopy(v_, vsize_, vsize_new);
delete[] v_;
v_ = v_new;
vsize_ = vsize_new;
}
v_[vused_] = other;
++vused_;
}
template<class T>
T* Stack<T>::Pop()
{
if (vused_ == 0)
{
throw "pop from empty stack";
}
else
{
T* result = v_[vused_ - 1];
--vused_;
return result;
}
}
// consider the following client code
string s1(s.Pop());
string s2;
s2 = s.Pop(); // if it fails, s will lost a element.
template<class T>
T* Stack<T>::Top() const
{
if (vused_ == 0)
{
throw "empty stack";
}
else
{
return v_[vused_ - 1];
}
}
template<class T>
void Stack<T>::Pop()
{
if (vused_ == 0)
{
throw "pop from empty stack";
}
else
{
--vused_;
}
}
template<class T>
bool Stack<T>::Empty() const
{
return (vused_ == 0);
}
// private base class or a memeber object:
//
// You need access to the class's protected members, or
// You need to override a virtual function, or
// The object needs to be constructed before other base subobjects
delete[] p;
//Destructors That Throw and Why They're Evil
//If the first destructor throws, then as it is written now,
//destroy will exit and the other four objects will never be destroyed. This is obviously not a good thing.
writing exception cod2
最新推荐文章于 2020-06-03 22:47:55 发布