I'm not sure why I'm getting this error class template has already been defined. The prof asked us to write a DLinkedOrderedList.template.h, Node.template.h, and Iterator.template.h. We're initially given DLinkedOrderedList.h. The error is only in DLinkedOrderedList.template.h and I'm not sure how to fix it so far:
我不确定为什么我得到这个错误类模板已经被定义。教授让我们写一个DLinkedOrderedList.template。h,Node.template。h,Iterator.template.h。我们最初DLinkedOrderedList.h。该错误仅出现在DLinkedOrderedList.template中。h和我不知道到目前为止该怎么解决:
DLinkedOrderedList.template.h
DLinkedOrderedList.template.h
//#include "DLinkedOrderedList.h"
template <class Item, class Order=IsLess>
class DLinkedOrderedList {
public:
/**
* Construct an empty list.
*/
DLinkedOrderedList(): m_head(NULL), m_tail(NULL), m_size(0);
/**
* Make a copy of a list.
*/
DLinkedOrderedList(DLinkedOrderedList<Item, Order> const& copy){
//copy constructor;
*m_head = new Node(*copy.m_head);
*m_tail = new Node(*copy.m_tail);
m_size = copy.m_size;
};
/**
* Destruct a list. Delete all dynamically allocated nodes.
*/
~DLinkedOrderedList(){
Node * here = m_head, * nextNode;
while ( here != NULL ) {
nextNode = here->next;
delete here;
here = nextNode;
}
};
/**
* Return the current list size. O(1).
*/
unsigned int size() const{
return m_size;
};
/**
* Answer: Is the list empty? O(1).
*/
bool isEmpty() const{
return (m_size == 0);
};
/**
* Get an iterator to the "beginning" or "off the ending" of this list.
* Default to a forward iterator. Note that the "beginning" of the list for
* a backward iterator is the tail of the list. Both are O(1).
*/
Iterator begin(Direction direction = FORWARD){return Iterator(m_head); };
Iterator end(Direction direction = FORWARD) {return Iterator(m_tail); }; //or return Iterator(NULL)
/**
* Insert an item into the correct location in the list according to the
* ordering defined by our templated Order class. If Order::compare(a, b) is
* true, then a must come before b in an ordered list. Return a forward
* iterator pointing to the inserted value. Ordering of duplicate items
* values does not matter, but each duplicate value should be included
* exactly in the list. E.g.,
*
* Inserting 2 into list: 1 <--> 2 <--> 3
* results in: 1 <--> 2 <--> 2 <--> 3
* It doesn't matter which "2 node" is the inserted node.
*
* This method should be O(n).
*/
Iterator insert(Item item){
//Node nodeItem;
//Iterator iteratorItem;
for (Iterator k = begin(); k != end(); k++){
if (Order::compare(item, *k )){
Iterator j = k-1;
Iterator l = k+1;
Node* here = k.m_ptr;
}
}
};
/**
* Remove a single "item"-valued item from the list and return true.
* If no such item is found, return false. O(n).
*/
bool remove(Item item){
//return true;
};
/**
* Remove the specific node that "itr" refers to, and return the node's
* value. "itr" should be adjusted to refer to the item in the "++ position"
* with respect to the removed node (see comment under Iterator's "kill"
* method for a detailed description). Note that this may be NULL! O(1).
*
* PRECONDITION: Iterator should be pointing at a valid position in the
* list.
*/
Item remove(Iterator& itr){
};
/**
* Remove all "item"-valued items from the list and return a count of the
* number of such items found and removed. O(n).
*/
unsigned int removeAll(Item item){};
};
DLinkedOrderedList.h
DLinkedOrderedList.h
#pragma once
/**
* YOU SHOULD NOT MODIFY ANY CODE IN THIS FILE.
*
* Comments in this file provide details on how to implement your assignment.
*/
/**
* StandardFunctors.h provides IsLess, the default Order for a
* DLinkedOrderedList.
*/
#include "StandardFunctors.h"
/**
* Direction of traversal for iterators.
*/
enum Direction {FORWARD=1, BACKWARD=2};
/**
* Class for self-ordering doubley linked list. YOU SHOULD NOT MODIFY ANYTHING
* "INSIDE" THIS CLASS! Instead, add your own implementations of the class
* interface to the three files that you will create -- the ones that are
* included below: DLinkedOrderedList.template.h, Node.template.h, and
* Iterator.template.h.
*/
template <class Item, class Order=IsLess>
class DLinkedOrderedList {
private:
/**
* Private class for list nodes. Node objects are dynamically allocated
* and freed in the appropriate constructors/operators/methods of the
* DLinkedOrderedList class.
*/
class Node {
public:
/**
* Construct a node containing val, with next = _next and prev = _prev.
*/
Node(Item val = Item(), Node* _next = NULL, Node* _prev = NULL);
/**
* Public members giving DLinkedOrderedList and Iterator (see class
* below) direct access to nodes' data.
*/
Item value;
Node* next;
Node* prev;
};
public:
/**
* Public iterator class wraps node pointers and supports minimum set.
* of operators for iterating forward and backward. Iterators store whether
* or not they are "forward iterators" or "backward iterators".
* Backward iterators have inverted "operator++" and "operator--" behaviour;
* i.e., the go to the previous node in the list using "++" and go the next
* node in the list with "--".
*/
class Iterator {
private:
/**
* A pointer to the node that this iterator refers to.
*/
Node* m_node;
/**
* A reference to the list that this iterator is "iterating over".
*/
DLinkedOrderedList<Item, Order>& m_list;
/**
* Defines "forward" or "backward" traversal iterator (see defnition of
* type Direction at the top of this file).
*/
Direction m_direction;
/**
* INVARIANT: m_node is EITHER an element of lst OR NULL.
*/
public:
/**
* Construct an Iterator from a pointer to a Node, a reference to the
* list, and a direction. Default to a forward iterator.
*
* PRECONDTION: ptr is EITHER an element of list OR NULL.
*/
Iterator(
Node* const node,
DLinkedOrderedList<Item, Order>& list,
Direction direction = FORWARD);
/**
* Increment an iterator; i.e., go to the "next node" according to
* the value of m_direction. I.e., "++" operator on forward
* iterators follows the NEXT pointer of the node; "++" operator on
* backward iterators follows the PREVIOUS pointer of the node.
*
* PRECONDTION: m_node is non-NULL.
*/
Iterator& operator++();
/**
* Decrement an iterator; i.e., go to the "previous node" according to
* the value of m_direction. I.e., "--" operator on forward
* iterators follows the PREVIOUS pointer of the node; "--" operator on
* backward iterators follows the NEXT pointer of the node.
*
* PRECONDTION: m_node is non-NULL.
*/
Iterator& operator--();
/**
* Answer the question: Does "this" NOT point to the same node as "b"?
*/
bool operator!=(Iterator const& b) const;
/**
* Overridden dereference operator* below allows to access item value
* contained in this iterator's node.
*
* HINT: "const'ness" of this function indicates that none of "this"'s
* members are changed while the function is running. It does not mean
* that the returned Item's reference is "const", which WOULD be a
* problem if we want to change item's value as in expression like:
*
* (*myItr) = 3; // Assuming MyItr is an iterator object.
*
* We DON'T have this problem because the returned Item& is NOT const.
* Expressions such as this are a valid, useful way of changing list
* item values.
*
* PRECONDTION: m_node is non-NULL.
*/
Item& operator*() const;
/**
* Delete/remove an item from the position correpsonding to the
* iterator) inside the list and returns the item value; the iterator
* should point to the "++ position" in the list according to the
* value of m_direction. I.e., forward iterators should
* point to the NEXT node after the deleted node; backward iterators
* should point to the PREVIOUS node prior to the deleted node. Note
* that the node in the "++ position" may be NULL.
*
* HINT 1: You can implement this really easily by exploiting one of
* DLinkedOrderedList's removal methods...
*
* HINT 2: When following HINT 1, let DLinkedOrderedList's removal method
* do the "++"-ing; make sure you don't increment twice by mistake!
*/
Item kill();
/**
* Make DLinkedOrderedList a friend. This gives it access protected and
* private members.
*
* HINT 3: Access to m_node greatly simplifies the implementation of
* DLinkedOrderedList's "Item remove(Iterator& itr)" (see below).
*/
friend class DLinkedOrderedList;
};
/**
* Construct an empty list.
*/
DLinkedOrderedList();
/**
* Make a copy of a list.
*/
DLinkedOrderedList(DLinkedOrderedList<Item, Order> const& copy);
/**
* Destruct a list. Delete all dynamically allocated nodes.
*/
~DLinkedOrderedList();
/**
* Return the current list size. O(1).
*/
unsigned int size() const;
/**
* Answer: Is the list empty? O(1).
*/
bool isEmpty() const;
/**
* Get an iterator to the "beginning" or "off the ending" of this list.
* Default to a forward iterator. Note that the "beginning" of the list for
* a backward iterator is the tail of the list. Both are O(1).
*/
Iterator begin(Direction direction = FORWARD);
Iterator end(Direction direction = FORWARD);
/**
* Insert an item into the correct location in the list according to the
* ordering defined by our templated Order class. If Order::compare(a, b) is
* true, then a must come before b in an ordered list. Return a forward
* iterator pointing to the inserted value. Ordering of duplicate items
* values does not matter, but each duplicate value should be included
* exactly in the list. E.g.,
*
* Inserting 2 into list: 1 <--> 2 <--> 3
* results in: 1 <--> 2 <--> 2 <--> 3
* It doesn't matter which "2 node" is the inserted node.
*
* This method should be O(n).
*/
Iterator insert(Item item);
/**
* Remove a single "item"-valued item from the list and return true.
* If no such item is found, return false. O(n).
*/
bool remove(Item item);
/**
* Remove the specific node that "itr" refers to, and return the node's
* value. "itr" should be adjusted to refer to the item in the "++ position"
* with respect to the removed node (see comment under Iterator's "kill"
* method for a detailed description). Note that this may be NULL! O(1).
*
* PRECONDITION: Iterator should be pointing at a valid position in the
* list.
*/
Item remove(Iterator& itr);
/**
* Remove all "item"-valued items from the list and return a count of the
* number of such items found and removed. O(n).
*/
unsigned int removeAll(Item item);
private:
/**
* Standard list data structure members: head of the list, tail of the list,
* size of the list.
*/
Node* m_head;
Node* m_tail;
unsigned int m_size;
};
/**
* CREATE THE THREE FILES #include'd BELOW AND INSERT YOUR CODE THERE!
* To make debugging easier, include these files in your Visual Studio project.
*/
#include "DLinkedOrderedList.template.h"
#include "Node.template.h"
#include "Iterator.template.h"
2 个解决方案
#1
3
The class template has already been defined in the "main" header "DLinkedOrderedList.h"
, so don't define it again in the "template" header. Just define the member functions, e.g.
类模板已经在"main" header "DLinkedOrderedList中定义。h,所以不要在“模板”标题中再次定义它。只需定义成员函数,例如
template <class Item, class Order>
DLinkedOrderedList::DLinkedOrderedList() :
m_head(NULL), m_tail(NULL), m_size(0)
{}
#2
1
Every header file should have a header guard:
每个头文件都应该有头文件保护:
#ifndef THIS_HEADER_H // Use a unique identifier for every file.
#define THIS_HEADER_H
// All contents of the header. Nothing goes before #ifndef or after #endif.
#endif
The lack of such a thing will cause a header included from different files to be processed twice, leading to literally all kinds of duplicate definition errors.
缺少这样的东西会导致包含在不同文件中的头两次被处理,从而导致各种重复的定义错误。
The example DLinkedOrderedList.h
uses a nonstandard facility to solve the same issue, #pragma once
, but this is not a generally accepted practice.
DLinkedOrderedList的例子。h使用一个非标准的工具来解决同一个问题#pragma一次,但是这并不是一个普遍接受的实践。
Furthermore, headers should all go at the top of a file, never at the bottom as your professor did. The canonical way to write a header (or any kind of program) is to state prerequisites, then implement additional functionality. There is no reason to diverge from the pattern here. You should be including DLinkedOrderedList.h
, not the other way around. (In this case it is beyond your control, but just FYI.)
此外,标题应该放在文件的顶部,而不是像教授那样放在底部。编写头(或任何类型的程序)的标准方法是声明先决条件,然后实现附加功能。没有理由偏离这里的模式。你应该包括DLinkedOrderedList。不是反过来的。(在这种情况下,它超出了你的控制范围,只是FYI。)
#1
3
The class template has already been defined in the "main" header "DLinkedOrderedList.h"
, so don't define it again in the "template" header. Just define the member functions, e.g.
类模板已经在"main" header "DLinkedOrderedList中定义。h,所以不要在“模板”标题中再次定义它。只需定义成员函数,例如
template <class Item, class Order>
DLinkedOrderedList::DLinkedOrderedList() :
m_head(NULL), m_tail(NULL), m_size(0)
{}
#2
1
Every header file should have a header guard:
每个头文件都应该有头文件保护:
#ifndef THIS_HEADER_H // Use a unique identifier for every file.
#define THIS_HEADER_H
// All contents of the header. Nothing goes before #ifndef or after #endif.
#endif
The lack of such a thing will cause a header included from different files to be processed twice, leading to literally all kinds of duplicate definition errors.
缺少这样的东西会导致包含在不同文件中的头两次被处理,从而导致各种重复的定义错误。
The example DLinkedOrderedList.h
uses a nonstandard facility to solve the same issue, #pragma once
, but this is not a generally accepted practice.
DLinkedOrderedList的例子。h使用一个非标准的工具来解决同一个问题#pragma一次,但是这并不是一个普遍接受的实践。
Furthermore, headers should all go at the top of a file, never at the bottom as your professor did. The canonical way to write a header (or any kind of program) is to state prerequisites, then implement additional functionality. There is no reason to diverge from the pattern here. You should be including DLinkedOrderedList.h
, not the other way around. (In this case it is beyond your control, but just FYI.)
此外,标题应该放在文件的顶部,而不是像教授那样放在底部。编写头(或任何类型的程序)的标准方法是声明先决条件,然后实现附加功能。没有理由偏离这里的模式。你应该包括DLinkedOrderedList。不是反过来的。(在这种情况下,它超出了你的控制范围,只是FYI。)