简体   繁体   中英

Friend function cannot access private data member (c++)

I have searched many different questions and could not find a solution that matched my specific problem. I have this header file for a queue:

#ifndef HEADERFILE
#define HEADERFILE
#include <iostream>
#include <vector>
using namespace std;

template<class myType>
class Queue{
  private:

    int size;
    vector<myType> list; 

  public:

    Queue(int);
    void Enqueue(myType);
    myType Dequeue();
    myType PeekFront();
    int length();
    void empty();
    myType Index(int);
    friend void printArray();

};

#endif

The issue in question is for friend void printArray . Here is the implementation file:

#include "queueTask1.h"
#include <vector>
#include <iostream>

using namespace std;

(Other function implementations)

void printArray(){
    for (int i = 0; i < list.size(); i++){
        cout << list.at(i) << ", ";
    }
    cout << endl;
}

The error when attempting to run this states that

'list' is not declared in this scope

however it is declared in the header file and all other member functions work fine. For some reason printArray cannot find the private data member list , even though it should be a friend function.

list is a non static data member. That means there is one list for each object. Since it is object dependent you need an object to access its list . The simplest way to do that is to pass the object to the function like

// forward declare the function, unless you want to define the function inside the class
template<class ElementType>
friend void printArray(const Queue<ElementType>&);

template<class myType>
class Queue{
    //...
    // declare the friendship
    template<class ElementType>
    friend void printArray(const Queue<ElementType>&);
    //...
};

// define the function
template<class ElementType>
void printArray(const Queue<ElementType>& q)
{
    for (int i = 0; i < q.list.size(); i++){
        cout << q.list.at(i) << ", ";
    }
    cout << endl;
}   

You also need to move your implementation of Queue into the header file since it is a temaplte. For more one this see: Why can templates only be implemented in the header file?

You need to pass the class instance into printArray() and then you can access private members of that instance. Otherwise, printArray() doesn't know which instance to use.

void printArray(Queue &myQueue){
    for (int i = 0; i < myQueue.list.size(); i++){
        cout << myQueue.list.at(i) << ", ";
    }
    cout << endl;
}

The declaration is very fine, but which instance of this class are you working on? list is accessible if you have object.list , but just list doesn't refer to anything. Pass an instance of your class, and use it to access list .

Something like:

void printArray(const Queue& object)

Myself, I'd do this:

template<class myType>
class Queue{
  // snip ...
  public:
  // snip ...
    template<class F>
    friend void foreach_element(Queue& q, F&& f) {
      for(auto&&e:list) f(e);
    }
    template<class F>
    friend void foreach_element(Queue const& q, F&& f) {
      for(auto&&e:list) f(e);
    }
};
template<class myType>
void printArray(Queue<myType> const& q) {
  foreach_element(q, [](auto&& e){ std::cout << e << ","; } );
  std::cout << std::endl;
}

note that printArray 's implementation has to go in the header, as it is a template function.

I exposed foreach_element to get at the elements, then had printArray be a non-friend that uses it.

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