Ошибка вне области при использовании частного наследования - PullRequest
0 голосов
/ 01 мая 2020

Я работаю со стеками в C ++, и я создал свой собственный класс стека, который наследуется в частном порядке от класса связанного списка, который я создал. Однако, когда я вызываю функцию класса стека, я получаю сообщение об ошибке, говорящее, что функция не была объявлена ​​в области видимости. Вот сообщение об ошибке:

Stack.h|15|error: 'insertAtFront' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]|

Кроме того, реализация моего стекового класса в основном просто использует некоторые функции-члены моего класса связанного списка для реализации функций pu sh () и pop () моего стек. Вот мой заголовочный файл стека:

#define STACK_H

#include "List.h" // List class definition

template< typename STACKTYPE >
class Stack : private List< STACKTYPE > 
{
public:
   // push calls the List function insertAtFront
   void push( const STACKTYPE &data ) 
   { 
      insertAtFront( data ); 
   } // end function push

   // pop calls the List function removeFromFront
   bool pop( STACKTYPE &data ) 
   { 
      return removeFromFront( data ); 
   } // end function pop

   // isStackEmpty calls the List function isEmpty
   bool isStackEmpty() const 
   { 
      return this->isEmpty();
   } // end function isStackEmpty

   // printStack calls the List function print
   void printStack() const 
   { 
      this->print();
   } // end function print 
}; // end class Stack

#endif

Вот мой заголовочный файл связанного списка также

#ifndef LIST_H
#define LIST_H

#include <iostream>
#include "ListNode.h" // ListNode class definition
using namespace std;

template< typename NODETYPE >
class List
{
public:
   List(); // constructor
   ~List(); // destructor
   ListNode<NODETYPE> * getFirstPointer() const;
   List<NODETYPE> concatList(List<NODETYPE> &) const;
    List<NODETYPE> reverseList() const;
   int getSize();
   void BubbleSort(ListNode <NODETYPE> *) const;
   double sum();
   void insertAtFront( const NODETYPE & );
   void insertAtBack( const NODETYPE & );
   bool removeFromFront( NODETYPE & );
   bool removeFromBack( NODETYPE & );
   bool isEmpty() const;
   void print() const;
private:
   ListNode< NODETYPE > *firstPtr; // pointer to first node
   ListNode< NODETYPE > *lastPtr; // pointer to last node
   int list_size = 0; //size of linked list

   // utility function to allocate new node
   ListNode< NODETYPE > *getNewNode( const NODETYPE & );
}; // end class List

// default constructor
template< typename NODETYPE >
List< NODETYPE >::List()
   : firstPtr( 0 ), lastPtr( 0 )
{
   // empty body
} // end List constructor

// destructor
template< typename NODETYPE >
List< NODETYPE >::~List()
{
   if ( !isEmpty() ) // List is not empty
   {
      cout << "Destroying nodes ...\n";

      ListNode< NODETYPE > *currentPtr = firstPtr;
      ListNode< NODETYPE > *tempPtr;

      while ( currentPtr != 0 ) // delete remaining nodes
      {
         tempPtr = currentPtr;
         cout << tempPtr->data << '\n';
         currentPtr = currentPtr->nextPtr;
         delete tempPtr;
      } // end while
   } // end if

   cout << "All nodes destroyed\n\n";
} // end List destructor

template< typename NODETYPE >
ListNode< NODETYPE > * List<NODETYPE>::getFirstPointer() const{
    return firstPtr;
}

template< typename NODETYPE >
List< NODETYPE > List<NODETYPE>::concatList(List<NODETYPE> &listobj) const{
    if(listobj.isEmpty()){
        cout<<"Empty List, concat failed"<<endl;
        return *this;
    }
    else {
        ListNode<NODETYPE> *ptr = getFirstPointer();
        NODETYPE data;
        while (ptr != 0){
            data = ptr->data;
            listobj.insertAtBack(data);
            ptr = ptr->nextPtr;
        }

        return listobj;
    }
}

template < typename NODETYPE >
int List< NODETYPE >::getSize() {
    return list_size;
}

template < typename NODETYPE >
List< NODETYPE > List< NODETYPE >::reverseList() const{
    List< NODETYPE > listobj;
    if(this->isEmpty()){
        cout<<"Empty List, reverse failed"<<endl;
        return *this;
    }
    else {
        ListNode<NODETYPE> *ptr = firstPtr;
        NODETYPE data;
        while (ptr != 0){
            data = ptr->data;
            listobj.insertAtFront(data);
            ptr = ptr->nextPtr;
        }

        return listobj;
    }
}

template <typename NODETYPE>
void List< NODETYPE >::BubbleSort(ListNode< NODETYPE > *ptr) const{
    int swapped;
    NODETYPE temp;
    ListNode <NODETYPE> *ptr1;
    ListNode <NODETYPE> *ptr2 = 0;

    if (ptr == 0)
        return;
    do{
        swapped = 0;
        ptr1 = ptr; // assign initial pointer
        while(ptr1->nextPtr != ptr2){
            if(ptr1->data > ptr1->nextPtr->data){
                temp = ptr1->data;
                ptr1->data = ptr1->nextPtr->data;
                ptr1->nextPtr->data = temp;
                swapped = 1;
        } //end if
        ptr1 = ptr1->nextPtr;
    }//end while
        ptr2 = ptr1;
    }//end do
    while(swapped);
}

template <typename NODETYPE>
double List< NODETYPE >::sum(){
    double sum = 0;
    if(this->isEmpty()){
        cout<<"Empty List, sum is 0"<<endl;
        return 0;
    }
    else {
        ListNode<NODETYPE> *ptr = firstPtr;
        NODETYPE data;
        while (ptr != 0){
            data = ptr->data;
            sum += data;
            ptr = ptr->nextPtr;
        }//end while
    } //end else
     return sum;
}

// insert node at front of list
template< typename NODETYPE >
void List< NODETYPE >::insertAtFront( const NODETYPE &value )
{
   ListNode< NODETYPE > *newPtr = getNewNode( value ); // new node

   if ( isEmpty() ) // List is empty
      firstPtr = lastPtr = newPtr; // new list has only one node
   else // List is not empty
   {
      newPtr->nextPtr = firstPtr; // point new node to previous 1st node
      firstPtr = newPtr; // aim firstPtr at new node
   } // end else
   list_size += 1;
} // end function insertAtFront

// insert node at back of list
template< typename NODETYPE >
void List< NODETYPE >::insertAtBack( const NODETYPE &value )
{
   ListNode< NODETYPE > *newPtr = getNewNode( value ); // new node

   if ( isEmpty() ) // List is empty
      firstPtr = lastPtr = newPtr; // new list has only one node
   else // List is not empty
   {
      lastPtr->nextPtr = newPtr; // update previous last node
      lastPtr = newPtr; // new last node
   } // end else
   list_size += 1;
} // end function insertAtBack

// delete node from front of list
template< typename NODETYPE >
bool List< NODETYPE >::removeFromFront( NODETYPE &value )
{
   if ( isEmpty() ) // List is empty
      return false; // delete unsuccessful
   else
   {
      ListNode< NODETYPE > *tempPtr = firstPtr; // hold tempPtr to delete

      if ( firstPtr == lastPtr )
         firstPtr = lastPtr = 0; // no nodes remain after removal
      else
         firstPtr = firstPtr->nextPtr; // point to previous 2nd node

      value = tempPtr->data; // return data being removed
      delete tempPtr; // reclaim previous front node
      list_size = list_size - 1;
      return true; // delete successful
   } // end else
} // end function removeFromFront

// delete node from back of list
template< typename NODETYPE >
bool List< NODETYPE >::removeFromBack( NODETYPE &value )
{
   if ( isEmpty() ) // List is empty
      return false; // delete unsuccessful
   else
   {
      ListNode< NODETYPE > *tempPtr = lastPtr; // hold tempPtr to delete

      if ( firstPtr == lastPtr ) // List has one element
         firstPtr = lastPtr = 0; // no nodes remain after removal
      else
      {
         ListNode< NODETYPE > *currentPtr = firstPtr;

         // locate second-to-last element
         while ( currentPtr->nextPtr != lastPtr )
            currentPtr = currentPtr->nextPtr; // move to next node

         lastPtr = currentPtr; // remove last node
         currentPtr->nextPtr = 0; // this is now the last node
      } // end else

      value = tempPtr->data; // return value from old last node
      delete tempPtr; // reclaim former last node
      list_size = list_size - 1;
      return true; // delete successful
   } // end else
} // end function removeFromBack

// is List empty?
template< typename NODETYPE >
bool List< NODETYPE >::isEmpty() const
{
   return firstPtr == 0;
} // end function isEmpty

// return pointer to newly allocated node
template< typename NODETYPE >
ListNode< NODETYPE > *List< NODETYPE >::getNewNode(
   const NODETYPE &value )
{
   return new ListNode< NODETYPE >( value );
} // end function getNewNode

// display contents of List
template< typename NODETYPE >
void List< NODETYPE >::print() const
{
   if ( isEmpty() ) // List is empty
   {
      cout << "The list is empty\n\n";
      return;
   } // end if

   ListNode< NODETYPE > *currentPtr = firstPtr;

   cout << "The list is: ";

   while ( currentPtr != 0 ) // get element data
   {
      cout << currentPtr->data << ' ';
      currentPtr = currentPtr->nextPtr;
   } // end while

   cout << "\n\n";
} // end function print

#endif

А вот мой файл реализации

int main()
{
   Stack< int > intStack; // create Stack of ints

   cout << "processing an integer Stack" << endl;

   // push integers onto intStack
   for ( int i = 0; i < 3; i++ ) 
   {
      intStack.push( i );
      intStack.printStack();
   } // end for
   }

I ' Мы также запустили пример кода в учебнике, в котором я учусь, и я получаю ту же ошибку. Любая помощь в отношении того, почему эта программа не компилируется, будет мне очень полезна. Спасибо.

1 Ответ

1 голос
/ 01 мая 2020

Если вы публично наследуете от базового класса, то компилятор знает, где искать имя:

struct A {
  void f();
};

struct B : A {
  void g() {
    f();  // ok, just look up 'f' in 'A'
  }
};

Однако, если вы наследуете от шаблона класса, компилятору нужна дополнительная информация:

template<typename T>
struct A {
  void f();
};

template<typename T>
struct B : A<T> {
  void g() {
    f();       // error, what 'f' ?
  }
};

Это потому, что компилятор не знает, где именно искать f. Например, A может иметь специализацию, которая изменяет определение f. Вы должны указать, что хотите использовать унаследованную функцию f:

template<typename T>
struct B : A<T> {
  void g() {
    this->f();  // ok
  }
};

или использовать оператор using, чтобы сказать, какой f вы хотите:

template<typename T>
struct B : A<T> {
  using A<T>::f;
  void g() {
    f();  // ok
  }
};

Итак, в вашем примере ваша push функция должна быть:

void push( const STACKTYPE &data ) 
{ 
  this->insertAtFront( data ); 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...