繁体   English   中英

硬件:C ++错误“试图初始化抽象基类”

[英]H/W: C++ Error “trying to initialize Abstract base class”

尝试初始化一个称为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()方法。 但是,此功能在对象的派生类“包装器”中实现:

#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方法吗? 不确定原始作者如何使它起作用(抓头)。

既然您已经解释了您要解决的问题,我建议:

  • 第一步是进行编译,您可以通过将CompareTo(Object&) const成员添加到StackAsLinkedList来进行StackAsLinkedList 您可以使用dynamic_cast或“ Visitor机制来查找dynamic_cast比较的对象是否是另一个集合。

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

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

至此,我们正在逐步取消设计。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM