0

I'm trying to pass in a head node to a function that recursively deletes everything from the LLL. But I'm not very good with classes. I've got one class for the LLL data called Node, and another called NodeList which manages all of the nodes.

The problem is that I can't access the private fields and I don't know how to get them in there. Because I don't want them public like a struct.

C++ Having trouble with syntax, so a class can pass data to other classes I've checked this link which said to make sure to have in the NodeList class Node * head, but I already have that.

C++ passing private data to other private functions in a class And I checked this one, but it was way over my head for the little C++ I know. Also I think this was just a pass by refrence issue.

This isn't the whole thing by the way, just the classes and the one function.

class NodeList
{
public:
    NodeList();
    ~NodeList();
//this should delete the whole list
    void delList(NodeList * head);

private:
//head
    NodeList * head;
};

//this is the nodestructkindathing
class Node
{
public:
    Node();
    ~Node();
private:
//next pointer
    Node * next;
    int data;
};

void NodeList::delList(NodeList * head)
{

    if (!head)
        return;

    delList(head->next);
    delete head;
}

NOTE: I changed delList and Node * head in the class to become NodeList * head and now I only recieve one error.

error: ‘class NodeList’ has no member named ‘next’

vvbudh
  • 3
  • 3
  • 1
    Make the `NodeList` a `friend` of `Node`? – Some programmer dude Mar 18 '18 at 16:56
  • A suggestion: declare the `Node` constructor as `Node(int value, Node * link = nullptr);`. Saves you from having to assign the members yourself later and makes it just about impossible to forget to set `next` to a useful value. – user4581301 Mar 18 '18 at 17:01
  • And be careful on that recursive `delList`. A long enough list will run you out of Automatic storage and result in a , wait for it, Stack Overflow. – user4581301 Mar 18 '18 at 17:02
  • Node::Node(int value, Node * link) { data = value; Node * link = NULL; } Is this what you're talking about? – vvbudh Mar 18 '18 at 17:06
  • More like: `Node(int value, Node * link = nullptr);` in the class definition and implement like `Node::Node(int value, Node * link) : next(link), data(value) { /* does nothing */ }`. If you instantiate as `Node A(42)`, you get `A` with `data` = 42 and `next` pointing to null. `Node B(24, &A);` give you `B` with `data` = 24 and `next` pointing to `A`. It's now much harder to make a trivial-but-common mistake. – user4581301 Mar 18 '18 at 17:27
  • The `:` in the implementation starts a [Member Initializer List](http://en.cppreference.com/w/cpp/language/initializer_list), a very handy and under-taught way to initialize class members BEFORE entering the the body of the constructor. You can't initialize in the constructor body, you have to assign, and some members are impossible or expensive to assign. – user4581301 Mar 18 '18 at 17:29
  • That was unsucccessful. I continue to get multiple errors. But If I change in the function delList from node * head to NodeList * head, I only get one error. error: ‘class NodeList’ has no member named ‘next’ – vvbudh Mar 18 '18 at 17:34
  • Wrong direction to change. `delList` deletes `Nodes`. Deleting anything else is a waste of your time. Did you make the change suggested by Some programmer dude? – user4581301 Mar 18 '18 at 17:42
  • I love abbreviations and acronyms. Please clarify your definition of LLL. For **L**inked **List**, I can only find 2 'L'. What's the third? But `LL` could refer to a `long long` integer too. – Thomas Matthews Mar 18 '18 at 18:25

1 Answers1

0

As suggested by Some programmer dude, make NodeList a friend of Node. When class A declares class B to be a friend, B can see and interact with the private members of A. Note that the reverse is not true. friendship is one way. A cannot see the private members of B unless B declares A to be a friend.

This one change will solve all of the problems asked in the question.

The rest of this code dump is to make writing a linked list a little easier for you. Linked lists are best considered a rite of passage for programmers. You'll find you rarely use them in real life programming, but they serve as a notorious weeder of CS students. Practically no one gets them right the first time or two. They require a moderate amount of care and attention to book keeping. Pen and paper step-by-step drawings of the list and the interactions you wish to perform on the list are highly recommended to help visualize and debug a linked list.

You may also find delving into pointers to pointers extremely helpful. For example, see the Alternative Using Pointer To Pointer section of this linked answer.

Comments embedded where needed.

#include <iostream>

class Node
{
    friend class NodeList; // NodeList, and no one else, can now see the private
                           // members of Node
public:
    // Node must be given a value and it not given a next, it's automatically NULL
    // this makes it almost impossible to not point link at something useful,
    // eliminating the most common of the trivial linked list bugs
    Node(int value, Node * link = nullptr);
    ~Node(); //if it doesn't do anything. Get rid of it. See the Rule of Zero
private:
    //next pointer
    Node * next;
    int data;
};

class NodeList
{
public:
    NodeList();
    ~NodeList();
    //this should delete the whole list
    void delList(Node * head);

private:
    //head
    Node * head;
};

Node::Node(int value, Node * link) : next(link), data(value)
{
    // test code
    std::cout << "Node data = " << data << " next = " << next << '\n';
}

Node::~Node()
{
    // test code
    std::cout << "~Node data = " << data << '\n';
}


NodeList::NodeList()
{
    // test code to give delList something to delete
    head = new Node(1,new Node(2,new Node(3)));
}
NodeList::~NodeList()
{
    delList(head);
}


//this is the nodestructkindathing
void NodeList::delList(Node * head) // watch out! Parameter head shadows member head!
{
    // Warning: This function is recursive and a potential stack-killer if given a 
    // long list. Prefer iteration here unless given a reason to do otherwise 
    // and guarantees on maximum list length
    if (!head)
        return;

    delList(head->next);
    delete head;
}

int main()
{
    NodeList test;
}

Expected output:

Node data = 3 next = 0
Node data = 2 next = 0x2ec6cc0
Node data = 1 next = 0x2ec6ce0
~Node data = 3
~Node data = 2
~Node data = 1

A discussion of the Rules of Three, Five and Zero. Understanding these rules is a must if you want a stable linked list or to program non-trivial systems in C++.

Documentation on friend.

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Woah I've never heard about friend before. I also don't know what std::cout does. (I'm assuming it's just cout without the headder library) We haven't been taught anything like this. – vvbudh Mar 18 '18 at 18:49
  • `std::cout` is the full name of `cout`. When you place `using namespace std;` in a file, you remove the need to specify you want the `std` namespace. Downside is the compiler can now make decisions like using `std::reverse` instead of your `reverse` function or `std::pow` instead of `pow`, [resulting in subtle differences in the results](https://stackoverflow.com/questions/33187956/c-pow-unusual-type-conversion). A lot more on the topic here: [Why is “using namespace std” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – user4581301 Mar 18 '18 at 19:07