无法将字段<object name =“”>声明为抽象类型</object>

时间:2013-11-05 02:26:14

标签: c++ object virtual declaration abstract

以下是我收到的错误,需要帮助解决...

g++ -g -c -std=c++11 main.cpp
In file included from main.cpp:3:0:
Executive.h:18:25: error: cannot declare field 'Executive::queue' to be of abstract type 'ListQueue<std::basic_string<char> >'
  ListQueue<std::string> queue;
                         ^
In file included from Executive.h:12:0,
                 from main.cpp:3:
ListQueue.h:8:7: note:   because the following virtual functions are pure within 'ListQueue<std::basic_string<char> >':
 class ListQueue : public QueueInterface<ItemType>
   ^

我不习惯使用“虚拟”类甚至C ++,但仍在学习,但我现在无法编译代码。虚拟类由教师提供,因此我将发布我的Executive,ListQueue和ArrayStack类的头文件。 ListQueue和ArrayStack是与它们的“虚拟”QueueInterface和StackInterface类相关的类。

Executive.h

    #include <iostream>
#include <string>
#include <fstream>

#include "ListQueue.h"
#include "ArrayStack.h"

class Executive
{
private:
    ListQueue<std::string> queue;
    ArrayStack<std::string> stack;
    std::string serving = "no one";
    std::string waiting = "no one";
    bool isWaiting = false;
    bool wasVIP = false;
    bool servingVIP = false;
public:

    /** Constructor reads in input file */
    Executive(std::istream& inputFile);

    /** Reads in and interprets the text file */
    void read(std::istream& is);

    /** Shows that the person currently being served finishes and the person waiting begins */  
    void done();

    /** Shows who is currently being served and who is next */
    void show();
};

ListQueue.h

 #include "QueueInterface.h"
#include "Node.h"

template<class ItemType>
class ListQueue : public QueueInterface<ItemType>
{
private:    
    Node<ItemType>* first; //front of queue
    Node<ItemType>* last; //end of queue

public:
    ListQueue();             // Default constructor
    bool isEmpty() const = 0;
    void enqueue(const ItemType& newEntry) throw (PrecondViolatedExcep) = 0;
    void dequeue() throw (PrecondViolatedExcep) = 0;
    ItemType peekFront() const throw (PrecondViolatedExcep) = 0;
}; // end ListQueue

ArrayStack.h

    #include "StackInterface.h"

const int MAX_STACK = 10;

template<class ItemType>
class ArrayStack : public StackInterface<ItemType>
{
private:    
    ItemType items[MAX_STACK]; // Array of stack items
    int      top;              // Index to top of stack

public:
    ArrayStack();             // Default constructor
    bool isEmpty() const;
    void push(const ItemType& newEntry) throw (PrecondViolatedExcep);
    void pop() throw (PrecondViolatedExcep);
    ItemType peek() const throw (PrecondViolatedExcep);
}; // end ArrayStack

StackInterface

template<typename ItemType>
class StackInterface
{
public:
   /** Sees whether this stack is empty.
    @return True if the stack is empty, or false if not. */
   virtual bool isEmpty() const = 0;

   /** Adds a new entry to the top of this stack.
    @pre a push is possible
    @post If the operation was successful, newEntry is at the top of the stack.
    @param newEntry The object to be added as a new entry. */
   virtual void push(const ItemType& newEntry)
        throw (PrecondViolatedExcep) = 0;

    /** Removes the top of this stack.
    @pre The stack is not empty.
    @post If the operation was successful, the top of the stack
    has been removed. */
   virtual void pop()
        throw (PrecondViolatedExcep) = 0;

   /** Returns the top of this stack.
    @pre The stack is not empty.
    @post The top of the stack has been returned, and
    the stack is unchanged.
    @return The top of the stack. */
   virtual ItemType peek() const throw (PrecondViolatedExcep) = 0;
}; // end StackInterface

QueueInterface

template<typename ItemType>
class QueueInterface
{
public:
   /** Sees whether this queue is empty.
    @return True if the queue is empty, or false if not. */
   virtual bool isEmpty() const = 0;

   /** Adds a new entry to the back of this queue.
    @pre an enqueue is possible
    @post If the operation was successful, newEntry is at the 
       back of the queue.
    @param newEntry  The object to be added as a new entry. */
   virtual void enqueue(const ItemType& newEntry)
        throw (PrecondViolatedExcep) = 0;

    /** Removes the front of this queue.
     @pre The queue is not empty.
     @post If the operation was successful, the front of the queue 
       has been removed. */
   virtual void dequeue()
        throw (PrecondViolatedExcep) = 0;

   /** Returns the front of this queue.
    @pre The queue is not empty.
    @post The front of the queue has been returned, and the
       queue is unchanged.
    @return The front of the queue. */
   virtual ItemType peekFront() const
        throw (PrecondViolatedExcep) = 0;
}; // end QueueInterface

2 个答案:

答案 0 :(得分:1)

您不能将队列声明为List&lt; std :: string&gt;类型;你可以使它成为抽象类型ListQueue&lt; std :: string&gt;的指针。与堆栈相同。

class Executive
{
        private:
    ListQueue<std::string> *queue;
    ArrayStack<std::string> *stack;
    std::string serving = "no one";
    std::string waiting = "no one";
    bool isWaiting = false;
    bool wasVIP = false;
    bool servingVIP = false;
public:
}

你不能这样做的原因是,如果它不是指针,编译器必须确定新类的内存形状,它需要知道类定义中字段类型的大小是。但是我不能为抽象类做这个,因为它不是一个完整的定义。如果你使它成为一个抽象类的指针,它可以解决,因为指针只是一个整数。


在与你交谈之后,我意识到了这个错误。你继承了老师给你的接口。这是一个工具,当你编写代码给别人一个合同,说我为我做了我想要的东西,这就是我将使用它的方式。

你教授给你的接口定义是空的,没有定义函数应该做的逻辑。你的类应该继承你已经完成的接口,但你的类也应该填写所有方法的细节。

例如:

#include "QueueInterface.h"
#include "Node.h"

template<class ItemType>
class ListQueue : public QueueInterface<ItemType>
{
private:    
    Node<ItemType>* first; //front of queue
    Node<ItemType>* last; //end of queue

public:
    ListQueue();             // Default constructor
    bool isEmpty() const
    {
       // add logic here that will determine if the queue is empty.
    }

    void enqueue(const ItemType& newEntry) throw (PrecondViolatedExcep)
    {
       // Add logic to add element to queue
    }

    void dequeue() throw (PrecondViolatedExcep)
    {
       // add  logic to remove element from queue
    }

    ItemType peekFront() const throw (PrecondViolatedExcep)
    {
       // add logic to look at next element in queue without removing it.
    }

}; // end ListQueue

一旦您填写了这些接口的逻辑,您的类现在将被完全定义,您可以使用它。如果您喜欢和构造函数,析构函数等,您不限于可以添加辅助方法的那些方法。但是您必须至少实现作为接口一部分的集合。

有道理吗?

这是否有意义。

答案 1 :(得分:0)

Executive.h:18:25: error: cannot declare field 'Executive::queue' to be of abstract type 'ListQueue<std::basic_string<char> >' ListQueue<std::string> queue;

QueueInterface似乎是一个抽象类。为了使用它,你已经从中派生了ListQueue类。

但是ListQueue类有以下内容:

bool isEmpty() const = 0;
void enqueue(const ItemType& newEntry) throw (PrecondViolatedExcep) = 0;
void dequeue() throw (PrecondViolatedExcep) = 0;
ItemType peekFront() const throw (PrecondViolatedExcep) = 0;  

这也使它变得抽象。

C ++类中最后带有= 0的任何方法都会使它成为纯虚方法,而类抽象类

现在抽象类无法实例化。这是因为,它的行为是未知的(纯虚函数的定义不存在)

请看以下示例:

class Mammal
{
    public:
        virtual void breath() = 0;
}

现在Mammal m之类的内容会引发错误。为什么?要理解这一点,请考虑以下代码:

// Assume the below line doesn't throw an error
Mammal m;

// m is now an object of type Mammal
m.breath();

您对m.breath()行有什么期望?它没有定义,编译器完全不知道要执行什么。这就是它不起作用的原因。

那我该怎么办? 从Mammal(抽象)类

中派生出一个类
class Horse : public Mammal
{
    public:
        void breath();
}

void Horse::breath()
{
    // Code for horse breathing
}

所以这里定义了breath()(即定义了哺乳动物的呼吸行为) 我现在可以这样做:

Horse h;
h.breath();

它会起作用!

如果你想知道有一个抽象类的意义,那是因为我可以有很多基类Mammal类,如下所示:

class Dog : public Mammal
{
    public:
        void breath()
        {
            // Dog's breathing code
        }
}

class Cat : public Mammal
{
    public:
        void breath()
        {
            // Cat's breathing code
        }
}

然后我可以做类似的事情:

// represents a generic mammal i.e it can be either a horse, a dog or a cat, that I can decide at run time
Mammal* m;

int i = 0;
cin >> i;
switch(i)
{
    case 0:
        m = new Horse();
    case 1:
        m = new Dog();
    case 2:
        m = new Cat();
    default:
        m = 0;
}

if(m!=0)
{
    m->breath();
    delete m;
}

这样你就可以在运行时调用适当的breath()

所以我想你已经知道你应该做什么了: 定义子类的方法定义(在您的情况下为ListQueue