简体   繁体   中英

C++ errors with template friend classes and

Im creating my own doubly linked list program (I know there is a list library). I have my main.cc with just my main function that provides a menu to choose the various options for my program and call the correct functions/objects. I then have 3 different header files containing class files, 1 is the general file for my doubly linked list functions, another is to turn the general DLL functions into queue functions and the last one is to convert the DLL functions to stack functions.

main.cc

#include <iostream>


#include "doubly-linked-list.h"
#include "DLLstack.h"
#include "DLLqueue.h"

using namespace std
int choice=0,choice2=0;

int main()
{
    int choice=0,choice2=0,i=0;
    DoublyLinkedList<int> lst;
    DLLstack stlist;
    while(1)
    {

        choice2=0;
        //ask user
        cout<<"\n1. Create Simple (Unsorted) List\n2. Create Sorted List\n";
        cout<<"3. Create LIFO Queue\n4. Create FIFO Queue(Stack)\n";
        cout<<"5. Exit Program\n";
        cout<<"Please choose an option\n";
        cin>>choice;

        while(choice==1)
        {

            //ask user 1.a
            cout<<"\n1. Enter integer for insertion at head of list\n2. Enter integer for insertion at tail of list\n";
            cout<<"3. Display and Delete integer at head\n4. Display and Delete integer at tail\n";
            cout<<"5. Search for integer in list and delete that node\n6.  Display Contents of list from head to tail in order\n7.  Exit\n";
            cout<<"Please choose an option\n";
            cin>>choice2;

            if(choice2==1)//1.1
            {cout<<"Enter integer to add to head\n";
                cin>>i;
                lst.addToDLLHead(i);
            }
            if(choice2==2)//1.2
            {
                cout<<"Enter integer to add to tail\n";
                cin>>i;
                lst.addToDLLTail(i);
            }
            if(choice2==3)//1.3
            { try{
                i=lst.deleteFromDLLHead ();
            } catch(int error_code)
                {
                    cerr<<"Error: "<<error_code<<endl;
                    switch(error_code)
                    {cout<<"Empty List\n";
                            return(1);
                    }
                }

                cout<<"The deleted int was "<<i<<endl;
            }
            if(choice2==4)//1.4
            { try{
                i=lst.deleteFromDLLTail ();
            } catch(int error_code)
                {
                    cerr<<"Error: "<<error_code<<endl;
                    switch(error_code)
                    {case 1:
                        cout<<"Empty List\n";
                            return(1);
                    }
                }
                cout<<"The deleted int was "<<i<<endl;
            }
            if(choice2==5)//1.5
            {
                cout<<"Enter Integer to search for and delete"<<endl;
                cin>>i;
                try{
                    lst.searchdelete (i);
                } catch(int error_code)
                {
                    cerr<<"Error: "<<error_code<<endl;
                    switch(error_code)
                    {cout<<"Empty List\n";
                            return(1);
                    }
                }
            }
            if(choice2==6)
            {lst.printlist ();}
            if(choice2==7) choice=0;
        }





        while(choice==2)
        {
            //ask user 2.b
            cout<<"\n1. Enter integer for sorted insertion(increasing order) into list\n2. Display and delete integer if present in list\n";
            cout<<"3. Display contents of sorted list of integers, in increasing order\n";
            cout<<"4. Exit program\n";
            cout<<"Please choose an option\n";
            cin>>choice2;

            if(choice2==1)//2.1
            {cout<<"Enter integer to add to the sorted list"<<endl;
                cin>>i;
                lst.addSorted (i);
            }
            if(choice2==2)
            {
                cout<<"Enter Integer to search for and delete"<<endl;
                cin>>i;
                try{
                    lst.searchdelete (i);
                } catch(int error_code)
                {
                    cerr<<"Error: "<<error_code<<endl;
                    switch(error_code)
                    {cout<<"Empty List\n";
                            return(1);
                    }
                }
            }
            if(choice2==3)
            {lst.printlist ();}
            if(choice2=4)
            {choice=0;}
        }






        while(choice==3)
        {
            cout<<"\n1. ENQUEUE\n2. DEQUEUE\n";
            cout<<"3. Print QUEUE\n";
            cout<<"4. Exit program\n";
            cout<<"Please choose an option\n";
            cin>>choice2;
            DLLQueue.qlst;

            if(choice2==1)
            {
                cout<<"Enter number to place in Queue"<<endl;
                cin>>i;
                qlst.enqueue(i);}
            if(choice2=2)
            {try{qlst.dequeue();
            } catch(int error_code)
                {
                    cerr<<"Error: "<<error_code<<endl;
                    switch(error_code)
                    {cout<<"Empty List\n";
                            return(1);
                    }
                }
            }
            if(choice2=3)
            {lst.printlist ();}
            if(choice2=4)
            {choice=0;}


        }

            while(choice==4)
            {
                cout<<"\n1. Push\n2. Pop\n";
                cout<<"3. Print STACK\n";
                cout<<"4. Exit program\n";
                cout<<"Please choose an option\n";
                cin>>choice2;
                if(choice2==1)
                {cout<<"Please enter value to place in stack"<<endl;
                    cin>>i;
                    stlst.push(i);
                }
                if(choice2==2)
                {stlst.pop();}
                if(choice2==3)
                {lst.printlist ();}
                if(choice2==4)
                {choice=0;}
            }






        } //original while

        return 0;
    }

doubly-linked-list.h

#ifndef DOUBLY_LINKED_LIST
#define DOUBLY_LINKED_LIST
#include <iostream>
using namespace std;

const int EMPTY_LIST=1;
template<class T>
class DLLNode
{
    friend class DoublyLinkedList;
    friend class DLLQueue;
    friend class DLLstack;
public:
    DLLNode(){next=prev=NULL;}
    DLLNode(const T& el, DLLNode *n=NULL, DLLNode *p=NULL)
{info=el;
    next=n;
    prev=p;
}
T info;
DLLNode<T> *next, *prev;
protected:
//T info;
//DLLNode<T> *next, *prev;
private:

};

template<class T>
class DoublyLinkedList
{
    friend class DLLQueue;
    friend class DLLstack;
public:
    DoublyLinkedList() {head=tail=NULL;} //good
    void addToDLLTail(const T&); //good
    T deleteFromDLLTail(); //good
    T isDLLEmpty() {return (head==NULL);} //good
    void addToDLLHead(const T&); //added
    T deleteFromDLLHead(); //added
    void deleteDLLNode(const T&); //added
    bool isInList(const T&) const; //added
    void addSorted(const T&); //added
    void printlist(); //added
    T searchdelete(const T&);


protected:

private:
DLLNode<T> *head, *tail;
};

template<class T>
T DoublyLinkedList<T>::deleteFromDLLTail(){
    if(head!=NULL){
        T el=tail->info;
        if(head==tail){
            delete tail;
            head=tail=NULL;
        }
        return el;
    }
    else throw(EMPTY_LIST);
}

template<class T>
void DoublyLinkedList<T>::addToDLLTail(const T& el) {
    if(tail!=NULL){
        tail=new DLLNode<T>(el,NULL,tail);
        tail->prev->next=tail;
    }
    else head=tail= new DLLNode<T>(el);
}

template<class T>
void DoublyLinkedList<T>::addToDLLHead (const T& el) {
    head = new DLLNode<T>(el,head);
    if(tail==NULL) tail=head;
}

template<class T>
T DoublyLinkedList<T>::deleteFromDLLHead (){
    if(head!=NULL)
    {
        int el=head->info;
        DLLNode<T> *tmp=head;
        if(head==tail)
        {head=tail=NULL;}
        else{head=head->next;}
        delete tmp;
        return(el);
        }
    else throw(EMPTY_LIST);
}

template<class T>
void DoublyLinkedList<T>::deleteDLLNode(const T& el) {  
if(head!=NULL){
   if(head==tail&&el==head->info) {
       delete head;
       head=tail=NULL;
   }
   else if(el==head->info){
       DLLNode<T> *tmp=head;
       head=head->next;
       head->prev=NULL;
       delete tmp;
   }
   else {
       DLLNode<T> *pred, *tmp;
       for(tmp=head->next;tmp!=NULL && tmp->info!=el;tmp=tmp->next);
       if(tmp!=NULL){
           pred=tmp->prev;
           pred->next=tmp->next;
           pred->next->prev=pred;

       if(tmp==tail) {tail=tail->prev;}
           delete tmp;
       }
   }
}
else throw(EMPTY_LIST);
}

template<class T>
bool DoublyLinkedList<T>::isInList(const T& el) const {
    DLLNode<T> *tmp;
    for(tmp=head;tmp!=NULL&&tmp->info !=el; tmp=tmp->next);
    return (tmp !=NULL);
}

template<class T>
void DoublyLinkedList<T>::addSorted(const T& i) {
    DLLNode<T> *tmp, *nxt;
    for(tmp=head;tmp->info<i;tmp=tmp->next);
    nxt=tmp->next;
    tmp->next= new DLLNode<T> (i,nxt,tmp);
    next->prev=tmp->next;
    delete tmp;
    delete nxt;
}

template<class T>
void DoublyLinkedList<T>::printlist() {
    DLLNode<T> *tmp;
    if(head!=NULL){
    for(tmp=head;tmp->next!=NULL;tmp=tmp->next){
        cout<<tmp->info<<endl;
    }
    }
}

template<class T>
T DoublyLinkedList<T>::searchdelete(const T& i)
{ DLLNode<T> *tmp;
    for(;tmp->info!=i&&tmp!=NULL;tmp=tmp->next){}
        delete DLLNode<T> (tmp);
    return(cout<<"Value Deleted from List\n");
}



#endif // DOUBLY_LINKED_LIST

DLLstack.h

#ifndef _DLLSTACK_H_
#define _DLLSTACK_H_
#include <iostream>
using namespace std;

#include "doubly-linked-list.h"
class DLLstack
{
    friend class<class T> DoublyLinkedList;
    friend class<class T> DLLNode;
public:
    DLLstack(){};
    bool isEmpty() const
{return lst.isEmpty();}
    void clear()
{
    while(!list.isEmpty()){
        lst.deleteFromDLLHead();}
}
int pop()
{return (lst.deleteFromHead();}
void push(const int& el);
{lst.addToDLLHead (el);}
int topEl()
{
    int topelement;
    topelement=lst.deleteFromDLLHead ();
    lst.addToDLLHead (topelement);
    return(topelement);
}
protected:

private:
DoublyLinkedList stlst;
};

#endif // _DLLSTACK_H_

DLLqueue.h

#ifndef _DLLQUEUE_H_
#define _DLLQUEUE_H_
#include <iostream>
using namespace std;
#include "doubly-linked-list.h"
template<class T>
class DLLQueue
{
    friend <class T> class DoublyLinkedList
    friend <class T> class DLLNode
public:

DLLQueue(){};
bool isEmpty() const
{ return lst.isEmpty();}
void enqueue(const T& el)
{ lst.addToDLLTail (el);}
T dequeue()
{ return {lst.deleteFromDLLHead ();}
T firstEl()
{
    T front_el;
    front_el=lst.deleteFromDLLHead ();
    lst.addToDLLHead (front_el);
    return(front_el);
}
~DLLQueue() {clear();}
protected:

private:
DoublyLinkedList qlst;
};

#endif // _DLLQUEUE_H_

Now I get 30 errors, but my main problem (i think) is that it says my friend function declarations in my DLLqueue.h file and DLLstack.h file are DLLqueue.h:11:9: error: expected unqualified-id before '<' token DLLstack.h:11:14: error: expected identifier before '<' token

as well as my lst object in both the stack and queue classes "was not declared in this scope"

doubly-linked-list.h:141:2: error: 'next' was not declared in this scope

there are more errors but I think these are causing the major problems and i need to fix these first to continue.

If you are wondering I am programming in the Ajuta IDE in Ubuntu

friend <class T> class DoublyLinkedList

should be

template <class U> friend class DoublyLinkedList;

or

friend class DoublyLinkedList<T>;

depending on which instantiations actually need to be friends; and likewise for the other friend declarations.

DoublyLinkedList qlst;

should be

DoublyLinkedList<T> qlst;

since DoublyLinkedList is a template, not a type.

There's shouldn't be a semicolon before the function body in DLLStack::push :

void push(const int& el);
{lst.addToDLLHead (el);}

You have an unwanted ( with no matching ) in DLLstack::pop :

{return (lst.deleteFromDLLHead();}

And an unwanted { in DLLQueue::deque :

{ return {lst.deleteFromDLLHead ();}

There are various typos (eg declaring a member stlst and referring to it variously as lst and list ) - the compiler errors will point you directly at these.

DoublyLinkedList::isDLLEmpty needs to be declared const , so it can be called from the const member functions of the other classes (once you've fixed the typos that call it isEmpty ).

In DoublyLinkedList::searchdelete , delete DLLNode<T>(tmp) should just be delete tmp . You also need to fix up the pointers in the nodes on either side of the deleted one, and return a value of type T (presumably i ), and fix the behaviour of the loop so it actually searches for the correct node (as it is, it iterates through to the end, then deletes the null pointer, with the result that it does nothing).

Finally, ~DLLQueue tries to call DoublyLinkedList::clear which doesn't exist. You should implement either that, or a destructor for DoublyLinkedList (or both). As it is, the list is a memory leak. It should also have a copy constructor and assignment operator (simply declared private if you don't want the class to be copyable).

Also, you shouldn't use reserved names (beginning with an underscore, such as _DLLQUEUE_H_ ) as include guards. You also shouldn't put using namespace std; in your header files; the user of the header file might not want the global namespace polluted.

Change your friend declaration to

template <class U> friend class DLLNode;

Also semicolons are missing here

class DLLQueue
{
    friend <class T> class DoublyLinkedList
    friend <class T> class DLLNode
  1. Don't write your own list, stack or queue. Use std::deque with std::stack and std::queue adaptors instead.
  2. Don't ever do using namespace std in the header.
  3. All your friend declarations use wrong syntax. It should be template <typename T> friend class X; (or with class instead of typename ). Also, identifiers are case sensitive, DLLStack and DLLstack are two completely different things.
  4. Your classes will not work properly with copying.
  5. Don't throw ints, use a proper subclass of std::exception instead.
  6. You don't use the template arguments in member variable definitions.

I don't see any more major problems, but I might be missing something in all the pointer stuff.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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