我正在使用Visiual Studio 2013.出于某种原因,我收到以下错误:
Error 1 error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Word &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@AAVWord@@@Z) referenced in function "protected: virtual void __thiscall BST<class Word>::visit(class BSTNode<class Word> *)" (?visit@?$BST@VWord@@@@MAEXPAV?$BSTNode@VWord@@@@@Z) C:\Users\Reuben\documents\visual studio 2013\Projects\CS321 Lab4\CS321 Lab4\main.obj CS321 Lab4
错误是由于这一特定行:
BST<Word> tree;
如果该行如下,那么它似乎编译得很好:
BST<int> tree;
或BST<string> tree;
所以出于某种原因,它不喜欢我定义的Word类的实现。以下是代码。
的main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "Word.h"
#include "genBST.h"
using namespace std;
int main()
{
BST<Word> tree;
system("pause");
return 0;
}
Word.h
#include <string>
#include <set>
using namespace std;
class Word{
public:
string* word;
set<int>* lineNums;
void addLineNum(int);
Word(string*, int);
Word();
friend ostream& operator<<(ostream& out, Word& pr);
friend bool operator==(Word, Word);
friend bool operator!=(Word, Word);
friend bool operator<(Word, Word);
friend bool operator<=(Word, Word);
friend bool operator>=(Word, Word);
friend bool operator>(Word, Word);
};
Word::Word(string* myWord, int myLineNum) {
word = myWord;
set<int>* lineNums = new set<int>();
lineNums->insert(myLineNum);
}
Word::Word()
{
word = new string("");
set<int>* lineNums = new set<int>();
lineNums->insert(1);
}
void Word::addLineNum(int line)
{
lineNums->insert(line);
}
//overload comparison operators
//take note that the order of these are important
//since some of the operators are defined in terms of the previously defined ones
bool operator==(Word word1, Word word2)
{
if (*(word1.word) == *(word2.word))
{
return true;
}
return false;
}
bool operator!=(Word word1, Word word2)
{
return !(word1 == word2);
}
bool operator<=(Word word1, Word word2)
{
if (*(word1.word) <= *(word2.word))
{
return true;
}
return false;
}
bool operator<(Word word1, Word word2)
{
if (word1 <= word2 && word1 != word2)
return true;
return false;
}
bool operator>(Word word1, Word word2)
{
return !(word1 <= word2);
}
bool operator>=(Word word1, Word word2)
{
return !(word1 < word2);
}
std::ostream& operator<<(std::ostream& out, const Word& word1)
{
out << *(word1.word);
out << ": ";
set<int>::iterator it;
for (it = word1.lineNums->begin(); it != word1.lineNums->end(); it++)
{
out << *it << " ";
}
return out;
}
最后一个文件是genBST.h。这是一个很长的文件,所以我最后发布它。该文件是作为我的作业的一部分提供给我的,我们不允许对此文件进行更改,否则我们将失去分数。
//************************ genBST.h **************************
// generic binary search tree
#include <queue>
#include <stack>
#ifndef BINARY_SEARCH_TREE
#define BINARY_SEARCH_TREE
template<class T>
class Stack : public stack<T> {
public:
T pop() {
T tmp = top();
stack<T>::pop();
return tmp;
}
};
template<class T>
class Queue : public queue<T> {
public:
T dequeue() {
T tmp = front();
queue<T>::pop();
return tmp;
}
void enqueue(const T& el) {
push(el);
}
};
template<class T> class BST;
template<class T>
class BSTNode {
public:
BSTNode() {
left = right = 0;
}
BSTNode(const T& e, BSTNode<T> *l = 0, BSTNode<T> *r = 0) {
el = e; left = l; right = r;
}
T el;
BSTNode<T> *left, *right;
};
template<class T>
class BST {
public:
BST() {
root = 0;
}
~BST() {
clear();
}
void clear() {
clear(root);
root = 0;
}
bool isEmpty() const {
return root == 0;
}
void preorder() {
preorder(root);
}
void inorder() {
inorder(root);
}
void postorder() {
postorder(root);
}
void insert(const T&);
void recursiveInsert(const T& el) {
recursiveInsert(root, el);
}
T* search(const T& el) const {
return search(root, el);
}
T* recursiveSearch(const T& el) const {
return recursiveSearch(root, el);
}
void deleteByCopying(BSTNode<T>*&);
void findAndDeleteByCopying(const T&);
void deleteByMerging(BSTNode<T>*&);
void findAndDeleteByMerging(const T&);
void iterativePreorder();
void iterativeInorder();
void iterativePostorder();
void breadthFirst();
void MorrisPreorder();
void MorrisInorder();
void MorrisPostorder();
void balance(T*, int, int);
protected:
BSTNode<T>* root;
void clear(BSTNode<T>*);
void recursiveInsert(BSTNode<T>*&, const T&);
T* search(BSTNode<T>*, const T&) const;
T* recursiveSearch(BSTNode<T>*, const T&) const;
void preorder(BSTNode<T>*);
void inorder(BSTNode<T>*);
void postorder(BSTNode<T>*);
virtual void visit(BSTNode<T>* p)
{
cout << p->el << ' ';
}
};
template<class T>
void BST<T>::clear(BSTNode<T> *p) {
if (p != 0) {
clear(p->left);
clear(p->right);
delete p;
}
}
template<class T>
void BST<T>::insert(const T& el) {
BSTNode<T> *p = root, *prev = 0;
while (p != 0) { // find a place for inserting new node;
prev = p;
if (el < p->el)
p = p->left;
else p = p->right;
}
if (root == 0) // tree is empty;
root = new BSTNode<T>(el);
else if (el < prev->el)
prev->left = new BSTNode<T>(el);
else prev->right = new BSTNode<T>(el);
}
template<class T>
void BST<T>::recursiveInsert(BSTNode<T>*& p, const T& el) {
if (p == 0)
p = new BSTNode<T>(el);
else if (el < p->el)
recursiveInsert(p->left, el);
else recursiveInsert(p->right, el);
}
template<class T>
T* BST<T>::search(BSTNode<T>* p, const T& el) const {
while (p != 0)
if (el == p->el)
return &p->el;
else if (el < p->el)
p = p->left;
else p = p->right;
return 0;
}
template<class T>
T* BST<T>::recursiveSearch(BSTNode<T>* p, const T& el) const {
if (p != 0)
if (el == p->el)
return &p->el;
else if (el < p->el)
return recursiveSearch(p->left, el);
else return recursiveSearch(p->right, el);
else return 0;
}
template<class T>
void BST<T>::inorder(BSTNode<T> *p) {
if (p != 0) {
inorder(p->left);
visit(p);
inorder(p->right);
}
}
template<class T>
void BST<T>::preorder(BSTNode<T> *p) {
if (p != 0) {
visit(p);
preorder(p->left);
preorder(p->right);
}
}
template<class T>
void BST<T>::postorder(BSTNode<T>* p) {
if (p != 0) {
postorder(p->left);
postorder(p->right);
visit(p);
}
}
template<class T>
void BST<T>::deleteByCopying(BSTNode<T>*& node) {
BSTNode<T> *previous, *tmp = node;
if (node->right == 0) // node has no right child;
node = node->left;
else if (node->left == 0) // node has no left child;
node = node->right;
else {
tmp = node->left // node has both children;
previous = node; // 1.
while (tmp->right != 0) { // 2.
previous = tmp;
tmp = tmp->right;
}
node->el = tmp->el; // 3.
if (previous == node)
previous->left = tmp->left;
else previous->right = tmp->left; // 4.
}
delete tmp; // 5.
}
// findAndDeleteByCopying() searches the tree to locate the node containing
// el. If the node is located, the function DeleteByCopying() is called.
template<class T>
void BST<T>::findAndDeleteByCopying(const T& el) {
BSTNode<T> *p = root, *prev = 0;
while (p != 0 && !(p->el == el)) {
prev = p;
if (el < p->el)
p = p->left;
else p = p->right;
}
if (p != 0 && p->el == el)
if (p == root)
deleteByCopying(root);
else if (prev->left == p)
deleteByCopying(prev->left);
else deleteByCopying(prev->right);
else if (root != 0)
cout << "el " << el << " is not in the tree\n";
else cout << "the tree is empty\n";
}
template<class T>
void BST<T>::deleteByMerging(BSTNode<T>*& node) {
BSTNode<T> *tmp = node;
if (node != 0) {
if (!node->right) // node has no right child: its left
node = node->left; // child (if any) is attached to its parent;
else if (node->left == 0) // node has no left child: its right
node = node->right; // child is attached to its parent;
else { // be ready for merging subtrees;
tmp = node->left; // 1. move left
while (tmp->right != 0)// 2. and then right as far as possible;
tmp = tmp->right;
tmp->right = // 3. establish the link between the
node->right; // the rightmost node of the left
// subtree and the right subtree;
tmp = node; // 4.
node = node->left; // 5.
}
delete tmp; // 6.
}
}
template<class T>
void BST<T>::findAndDeleteByMerging(const T& el) {
BSTNode<T> *node = root, *prev = 0;
while (node != 0) {
if (node->el == el)
break;
prev = node;
if (el < node->el)
node = node->left;
else node = node->right;
}
if (node != 0 && node->el == el)
if (node == root)
deleteByMerging(root);
else if (prev->left == node)
deleteByMerging(prev->left);
else deleteByMerging(prev->right);
else if (root != 0)
cout << "el " << el << " is not in the tree\n";
else cout << "the tree is empty\n";
}
template<class T>
void BST<T>::iterativePreorder() {
Stack<BSTNode<T>*> travStack;
BSTNode<T> *p = root;
if (p != 0) {
travStack.push(p);
while (!travStack.empty()) {
p = travStack.pop();
visit(p);
if (p->right != 0)
travStack.push(p->right);
if (p->left != 0) // left child pushed after right
travStack.push(p->left); // to be on the top of the stack;
}
}
}
template<class T>
void BST<T>::iterativeInorder() {
Stack<BSTNode<T>*> travStack;
BSTNode<T> *p = root;
while (p != 0) {
while (p != 0) { // stack the right child (if any)
if (p->right) // and the node itself when going
travStack.push(p->right); // to the left;
travStack.push(p);
p = p->left;
}
p = travStack.pop(); // pop a node with no left child
while (!travStack.empty() && p->right == 0) { // visit it and all nodes
visit(p); // with no right child;
p = travStack.pop();
}
visit(p); // visit also the first node with
if (!travStack.empty()) // a right child (if any);
p = travStack.pop();
else p = 0;
}
}
template<class T>
void BST<T>::iterativePostorder() {
Stack<BSTNode<T>*> travStack;
BSTNode<T>* p = root, *q = root;
while (p != 0) {
for (; p->left != 0; p = p->left)
travStack.push(p);
while (p->right == 0 || p->right == q) {
visit(p);
q = p;
if (travStack.empty())
return;
p = travStack.pop();
}
travStack.push(p);
p = p->right;
}
}
template<class T>
void BST<T>::breadthFirst() {
Queue<BSTNode<T>*> queue;
BSTNode<T> *p = root;
if (p != 0) {
queue.enqueue(p);
while (!queue.empty()) {
p = queue.dequeue();
visit(p);
if (p->left != 0)
queue.enqueue(p->left);
if (p->right != 0)
queue.enqueue(p->right);
}
}
}
template<class T>
void BST<T>::MorrisInorder() {
BSTNode<T> *p = root, *tmp;
while (p != 0)
if (p->left == 0) {
visit(p);
p = p->right;
}
else {
tmp = p->left;
while (tmp->right != 0 &&// go to the rightmost node of
tmp->right != p) // the left subtree or
tmp = tmp->right; // to the temporary parent of p;
if (tmp->right == 0) { // if 'true' rightmost node was
tmp->right = p; // reached, make it a temporary
p = p->left; // parent of the current root,
}
else { // else a temporary parent has been
visit(p); // found; visit node p and then cut
tmp->right = 0; // the right pointer of the current
p = p->right; // parent, whereby it ceases to be
} // a parent;
}
}
template<class T>
void BST<T>::MorrisPreorder() {
BSTNode<T> *p = root, *tmp;
while (p != 0) {
if (p->left == 0) {
visit(p);
p = p->right;
}
else {
tmp = p->left;
while (tmp->right != 0 &&// go to the rightmost node of
tmp->right != p) // the left subtree or
tmp = tmp->right; // to the temporary parent of p;
if (tmp->right == 0) { // if 'true' rightmost node was
visit(p); // reached, visit the root and
tmp->right = p; // make the rightmost node a temporary
p = p->left; // parent of the current root,
}
else { // else a temporary parent has been
tmp->right = 0; // found; cut the right pointer of
p = p->right; // the current parent, whereby it ceases
} // to be a parent;
}
}
}
template<class T>
void BST<T>::MorrisPostorder() {
BSTNode<T> *p = new BSTNode<T>(), *tmp, *q, *r, *s;
p->left = root;
while (p != 0)
if (p->left == 0)
p = p->right;
else {
tmp = p->left;
while (tmp->right != 0 &&// go to the rightmost node of
tmp->right != p) // the left subtree or
tmp = tmp->right; // to the temporary parent of p;
if (tmp->right == 0) { // if 'true' rightmost node was
tmp->right = p; // reached, make it a temporary
p = p->left; // parent of the current root,
}
else { // else a temporary parent has been found;
// process nodes between p->left (included) and p (excluded)
// extended to the right in modified tree in reverse order;
// the first loop descends this chain of nodes and reverses
// right pointers; the second loop goes back, visits nodes,
// and reverses right pointers again to restore the pointers
// to their original setting;
for (q = p->left, r = q->right, s = r->right;
r != p; q = r, r = s, s = s->right)
r->right = q;
for (s = q->right; q != p->left;
q->right = r, r = q, q = s, s = s->right)
visit(q);
visit(p->left); // visit node p->left and then cut
tmp->right = 0; // the right pointer of the current
p = p->right; // parent, whereby it ceases to be
} // a parent;
}
}
template<class T>
void BST<T>::balance(T data[], int first, int last) {
if (first <= last) {
int middle = (first + last) / 2;
insert(data[middle]);
balance(data, first, middle - 1);
balance(data, middle + 1, last);
}
}
#endif
任何帮助将不胜感激!我还在学习c ++的基础知识,我转学,所以我正在努力学习c ++(而不是Java,这是我之前在其他学校所做的)。提前谢谢!
编辑:哎呀,我愚蠢,下面一行代码:friend ostream& operator<<(ostream& out, Word& pr);
应该(我认为):
friend ostream& operator<<(ostream, const Word);
然而,在此更改后,我仍然收到以下错误:
Error 1 error C2593: 'operator <<' is ambiguous c:\users\reuben\documents\visual studio 2013\projects\cs321 lab4\cs321 lab4\genbst.h 105 1 CS321 Lab4
105行引用的是函数中的语句(在genBST.h文件中):
virtual void visit(BSTNode<T>* p)
{
cout << p->el << ' ';
}
编辑v2: 好的,我已经改变了代码,现在似乎工作了。我刚刚放置了&lt;&lt;的实现声明中的运算符如下:
class Word{
public:
string* word;
set<int>* lineNums;
void addLineNum(int);
Word(string*, int);
Word();
friend ostream& operator<<(ostream& out, const Word& word1 )
{
out << *(word1.word);
out << ": ";
set<int>::iterator it;
for (it = word1.lineNums->begin(); it != word1.lineNums->end(); it++)
{
out << *it << " ";
}
return out;
};
friend bool operator==(Word, Word);
friend bool operator!=(Word, Word);
friend bool operator<(Word, Word);
friend bool operator<=(Word, Word);
friend bool operator>=(Word, Word);
friend bool operator>(Word, Word);
};
它似乎现在有效。
答案 0 :(得分:2)
我注意到你的课程定义中有:
class Word{
public:
string* word;
set<int>* lineNums;
void addLineNum(int);
Word(string*, int);
Word();
friend ostream& operator<<(ostream& out, Word& pr);
const
Word & pr
然而,在您的代码中稍后您有:
std::ostream& operator<<(std::ostream& out, const Word& word1)
看,在Word&amp;之前有一个const。 WORD1
应该使它们相同(都有const
),我认为
答案 1 :(得分:0)
我在Visual Stdio 2010上试过你的代码(我没有2013)。 在我添加关键字const(在Word&amp; pr之前)之前,我遇到了与您相同的错误。 但是,在我添加const后,它已成功构建。
添加关键字const后出现的错误是什么?在此详细发布。