2011-10-27 5 views
0

Stack 클래스의 파생 클래스 인 StackAsLinkedList라는 클래스를 초기화하려고합니다. 여기서 사용할 수있는 테스트 코드는 http://www.brpreiss.com/books/opus4/입니다. 그러나H/W : C++ 오류 "추상 기본 클래스를 초기화하려고합니다"

, 나는 오류가이 코드를 인스턴스화하려고 얻을 주() :

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 

편집 : 컴파일러에서 Object의 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() override;를 쓸 수 있으며 컴파일러는 일치하지 않는지 알려줍니다. 컴파일러가 그 오류와 함께 뱉어 낸 경고도 표시해야합니다. –

+2

컨테이너의 정의를 표시해야합니다. – Puppy

+0

@DeadMG : 당신이 대답을해야한다고 생각합니다. 문제가되는 것이 거의 확실합니다. –

답변

3

, 내가 제안 :

  • 첫 번째 단계는 당신이 StackAsLinkedListCompareTo(Object&) const 멤버를 추가 할 수있는 컴파일받을 것입니다. 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&)을 호출합니다. Visitor을 다형성 컬렉션에서 올바르게 수행하려면 각 구성원마다 가상 Accept 함수를 호출해야합니다.

이 시점까지는 설계를 폐지하고 있습니다.

관련 문제