2011-10-27 52 views
0

尝试初始化一个名为StackAsLinkedList的类,该类应该是抽象类Stack的派生类(测试代码可在此处获得:http://www.brpreiss.com/books/opus4/)。H/W:C++错误“尝试初始化抽象基类”

但是,我得到一个错误试图实例在此代码的main():

StackAsLinkedList stack; 

error C2259: 'StackAsLinkedList' : cannot instantiate abstract class 

我感到困惑的这个,因为我认为StackAsLinkedList被定义为一个派生类栈:

#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 

编辑:它似乎编译器说在对象中的CompareTo()方法没有在任何派生类中实现。但是,此功能在派生类对象的所谓“包装”来实现:

#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 

但堆栈不从包装继承 - 所以我猜这意味着另一CompareTo方法需要对协议栈来实现?不知道原作者如何得到这个工作(划痕头)。

+1

你使用什么编译器?使用MSVC++或更新版本的gcc,你可以编写Object&Pop()覆盖;并且编译器会让你知道它是否不匹配。您还需要显示编译器吐出的任何警告以及该错误。 –

+2

您需要显示Container的定义 – Puppy

+0

@DeadMG:我认为您需要做出答案,这几乎肯定会成为问题。 –

回答

3

既然你现在解释你试图解决它,我建议:

  • 第一步是把它编译,您可以通过添加CompareTo(Object&) const成员StackAsLinkedList做。您可以使用dynamic_castVisitor机器来查明对象是否是另一个集合。

  • 接下来,在被调用者存储对象并在函数返回后使用的任何情况下,删除引用参数。并根除引用返回类型,其中所有权正在转移。您可以使用指针,也可以将集合更改为按值传递(但如果集合应该是多态的,则不要传值)。你会得到:

    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在多态集合上正确执行。

我们正在努力取消设计的这一点。