以下是我收到的错误,需要帮助解决...
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
答案 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
)