尝试初始化一个名为StackAsLinkedList的类,它应该是抽象类Stack的派生类(测试代码可以在这里找到:http://www.brpreiss.com/books/opus4/)。
但是,尝试在main()中实例化此代码时出错:
StackAsLinkedList stack;
error C2259: 'StackAsLinkedList' : cannot instantiate abstract class
我对此感到困惑,因为我认为StackAsLinkedList被定义为Stack的派生类:
#ifndef STACK_H
#define STACK_H
#include "object.h"
#include "linkList.h"
#include "container.h"
class Stack : public virtual Container
{
public:
virtual Object& Top () const = 0;
virtual void Push (Object&) = 0;
virtual Object& Pop () = 0;
};
class StackAsLinkedList : public Stack
{
LinkedList<Object*> list;
class Iter;
public:
StackAsLinkedList () : list() {}
~StackAsLinkedList() { Purge(); }
//
// Push, Pop and Top
//
void Push(Object& object);
Object& Pop();
Object& Top() const;
//
// purge elements from, and accept elements onto, the list
//
void Purge();
void Accept (Visitor&) const;
friend class Iter;
};
class StackAsLinkedList::Iter : public Iterator
{
StackAsLinkedList const& stack;
ListElement<Object*> const* position;
public:
Iter (StackAsLinkedList const& _stack) : stack(_stack) { Reset(); }
//
// determine whether iterator is pointing at null
//
bool IsDone() const { return position == 0; }
//
// overloaded dereference and increment operator
//
Object& operator*() const;
void operator++() const;
void Reset() { position = stack.list.Head(); }
};
#endif
实施:
#include "stack.h"
void StackAsLinkedList::Purge()
{
if ( IsOwner() )
{
ListElement<Object*> const* ptr;
for(ptr = list.Head(); ptr != 0; ptr = ptr->Next() )
delete ptr->Datum();
list.Purge();
count = 0;
}
}
void StackAsLinkedList::Push(Object& object)
{
list.Prepend(&object);
++count;
}
Object& StackAsLinkedList::Pop()
{
if(count == 0)
throw domain_error ("stack is empty");
Object& result = *list.First();
list.Extract(&result);
--count;
return result;
}
Object& StackAsLinkedList::Top() const
{
if(count == 0)
throw domain_error ("stack is empty");
return *list.First();
}
void StackAsLinkedList::Accept(Visitor& visitor) const
{
ListElement<Object*> const* ptr;
for(ptr = list.Head(); ptr != 0 && !visitor.IsDone(); ptr = ptr->Next())
visitor.Visit(*ptr->Datum());
}
类容器:
#ifndef CONTAINER_H
#define CONTAINER_H
#include "object.h"
#include "visitor.h"
#include "iterator.h"
#include "ownership.h"
class Container : public virtual Object, public virtual Ownership
{
protected:
unsigned int count;
Container () : count(0) {}
public:
virtual unsigned int Count () const { return count; }
virtual bool IsEmpty () const { return Count () == 0; }
virtual bool IsFull () const { return false; }
//virtual HashValue Hash () const;
virtual void Put (ostream&) const;
virtual Iterator& NewIterator () const { return *new NullIterator (); }
virtual void Purge () = 0;
virtual void Accept (Visitor&) const = 0;
};
#endif
编辑:似乎编译器说Object中的CompareTo()方法没有在任何派生类中实现。但是,此功能在名为“Wrapper”的派生类Object中实现:
#ifndef WRAPPER_H
#define WRAPPER_H
#include "object.h"
template <class T>
class Wrapper : public Object
{
protected:
T datum;
int CompareTo (Object const&) const;
public:
Wrapper ();
Wrapper (T const&);
Wrapper& operator = (T const&);
operator T const& () const;
//HashValue Hash () const;
void Put (ostream&) const;
};
//
// typedefs for for Wrappers representing different primitive
// data types
//
typedef Wrapper <int> Int;
typedef Wrapper <char> Char;
typedef Wrapper <double> Double;
typedef Wrapper <std::string> String;
#include "wrapper.inc"
#endif
但是Stack不会从Wrapper继承 - 所以我猜这意味着需要为Stack实现另一个CompareTo方法?不确定原作者是如何工作的(划痕头)。
答案 0 :(得分:3)
由于您现在已经解释过您正在尝试修复它,我建议:
第一步是进行编译,您可以通过向CompareTo(Object&) const
添加StackAsLinkedList
成员来进行编译。您可以使用dynamic_cast
或Visitor
机制来确定与之比较的对象是否是另一个集合。
接下来,在被调用者存储对象并在函数返回后使用的任何情况下,删除引用参数。并根除所有权转移的参考回报类型。您可以使用指针,也可以将集合更改为按值传递(但如果集合应该是多态的,则不要传递值)。你会得到:
class Stack : public virtual Container
{
public:
virtual Object& Top () const = 0; // short-term access to object, no ownership transfer, reference is ok here.
virtual void Push (Object*) = 0; // pointer kept, ownership transfer, use pointer
virtual Object* Pop () = 0; // ownership transfer (caller must delete), use pointer
};
然后,你应该对Visitor
实现中的破坏做些什么。现在,无论动态类型如何,Accept
始终会调用Visit(Object&)
。您需要在每个成员上调用虚拟Accept
函数,以便让Visitor
在多态集合上正确执行。
到目前为止,我们正在努力取消设计。