-3

I created a linked list in c++. First I created a class Node then another class called List. My program runs perfectly. The thing is, I don't understand why there is no inheritance between Node and List so that List class can access the public methods of Node.
I made some changes and derived List from Node and its working. So how could it run with inheritance and without inheritance?

#include <iostream>
#include <stdlib.h>

using namespace std;

/* The Node class */
class Node
{
private:
    int object;
    Node * nextNode;

public:
//mutator and Accessor for Node values
    void set(int object)
    {
        this->object = object;
    }
    int get()
    {
        return object;
    }

//mutator and Accessor for Node Address
    void setNext(Node * nextNode)
    {
        this->nextNode = nextNode;
    }
    Node * getNext()
    {
        return nextNode;
    }
};


/* The List class */
class List : public Node
{
private:
    int size;   // List Size ( number of nodes )
    Node * headNode;    // address of starting node of list
    Node * currentNode; // address of Current node of list
    Node * lastCurrentNode; // address of previous node of list

public:
    /* Constructor */
    List()
    {
        headNode = new Node();          // creating new node and store its address in headNode  as its start of list
        headNode->setNext(NULL);    // the headNode is not connecting to any other node
        currentNode = NULL;             // as theres only head node so currentNode is empty
        lastCurrentNode = NULL;      //  Previous Node is also empty because there's only headNode
        size = 0;                               // Lisrs Size = 0 because theres no Value/data/object inside the list
    }

    /* add() class method */
add (int addObject)
{
    Node * newNode = new Node();    // creating/adding new node and store its address in newNode Pointer
    newNode->set(addObject);           // Add Value/data/object in the node just created

    if( currentNode != NULL )   // at first time when Current Node pointer is not pointing to any node in the list
    {
        newNode->setNext(currentNode->getNext());   // get adddress of node where current node will go and store that in the nextNode Pointer which is now called by our new node pointer so the addres that currentNode had now os taken and given to the new node
        currentNode->setNext( newNode );                  // address of new node we just created is now stored in current node
        lastCurrentNode = currentNode;                      // move Lastcurrent node to the current node position
        currentNode = newNode;                                 //   move currentNode pointer to the newNode we created;
    }
    // if current node is not pointing to any node (first time)
    else
    {
        newNode->setNext(NULL);             // new node we created will not point to any other next node because there's no one
        headNode->setNext(newNode);     //  head node now is pointing to the new node we created
        lastCurrentNode = headNode;      // lastCurrent node is now position to headNode so we can go back
        currentNode = newNode;             // current node is now position to the new node we created
    }
    size ++;        // as there's new new in the list increase its size to +1
}

/* get() class method */
    get()
    {
        if (currentNode != NULL)
        return currentNode->get();      // if current node is not null give the value where the current node is
    }

    /* next() class method */
    next()
    {
        if (currentNode == NULL)
        {
            return false;
        }

        lastCurrentNode = currentNode;  // move lastCurent node tot he position of current node
        currentNode = currentNode->getNext();       // move current node to the next node

        if (currentNode == NULL || size == 0)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
friend void traverse(List list);
friend List addNodes();

};

/* Friend function to traverse linked list */
void traverse(List list)    // friend function will get the object of List class
{
    Node* savedCurrentNode = list.currentNode;  // create new node pointer and assign it the address of current node
    list.currentNode = list.headNode;                   // move current node to the headNode ( starting of the list)
    for(int i = 1; list.next(); i++)                               // while we dnt reached to the end of list or not get false from next function
    {
        cout << "\n Element " << i << "  =  " << list.get();        // traverse every node and display its value
    }
    list.currentNode = savedCurrentNode;            // after traversing the whole nodes in the list move the current node to the position where it was befor e
}

/* Friend function to add Nodes into the list */
List addNodes()
{
    List list;
    list.add(2);
    list.add(6);
    list.add(8);
    list.add(7);
    list.add(1);

    cout << "\n List size = " << list.size <<'\n';

    return list;
}

int main()
{
    List list = addNodes();
    traverse(list);
}

Adapted from comment by Asker:

Can anybody just explain "How can 2nd class be able to use the public methods of 1st class while there's no inheritance b/w them? Does the 2nd class not have to be derived from 1st class so it can be able to point to the methods of base class (1st)?

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • 4
    An Inheritance relationship between `Node` and `List` implies that one is a type of the other. This would be an odd choice as a list generally contains a chain of nodes. `List` is not a `Node` and `Node` certainly isn't a `List` – user4581301 Nov 09 '18 at 23:15
  • 2
    As a tip for the future, try to don't over comment your code. Commenting code is a good thing. Don't comment code is bad. Over comment code is bad too. You should comment for documentation purposes and non trivial functions/methods and pretty complex parts of code. For example: `void add(int addObject)` really doesnt need that comment, it's obvious that that method will add. `Node * newNode = new Node();` is pretty obvious too. You must comment your code to help other profesionals, not to teach rookies. – LuisGP Nov 09 '18 at 23:28
  • 1
    if (ordinary) code needs comments, don't write comments but rewrite the code. – Swordfish Nov 09 '18 at 23:35

1 Answers1

2

Inheritance is the wrong thingtm to do in that case. As mentioned in the comments, inheritance models a "is-a" relationship:

a Ferrari is a car
a Mercedes is a car ... both have four wheels and n doors. So
a general car has four wheels and n doors which Ferrari and Mercedes inherit.

But a list (a container) is certainliy not a node. From your code, a list would have:

a value int object ... what is the value of a list? Makes no sense.
a pointer nextNode ... what is the "next node" of a list? another list? Makes no sense.
functions set(int object) and int get() ... set/get what? The value of a list? Makes no sense
functions setNext(Node * nextNode) and Node* getNext() ... as above: what is "the next node" of a list? Makes no sense.

The pattern you want to apply is composition, which models a "has-a" relationship:

a Ferrari has a steering wheel
a Mercedes has a steering wheel
a general car has a steering wheel

Your

list has a first node.

. o O ( your question makes me think of a german author that insisted that a WurstBrot should inherit from Wurst and Brot which in turn inherit Supermarket [sic])

btw: the code you have shown in your question should not compile. Several functions are missing a return type.

You should adhere to the Liskov Substitution Principle which states, that

in a computer program, if S is a subtype of [= inherits from] T, then objects of type T may be replaced with objects of type S (i.e. an object of type T may be substituted with any object of a subtype S) without altering any of the desirable properties of the program (correctness, task performed, etc.).

As to your code, already the c-tor of List makes me stumble:

List()
{
    headNode = new Node();     // why does an empty list have a Node thats its head?
    headNode->setNext(NULL);   // that is something the c-tor of Node should do
    currentNode = NULL;        // not sure what currentNode is supposed to be
    lastCurrentNode = NULL;    // contradicts my assumption from above that lastCurrentNode
                               // was a pointer to the last node of the List;
                               // you created a first Node so the last node should be
                               // pointing to headNode
    size = 0; // hm. Now you say your list is empty but you created a Node?
}
Swordfish
  • 12,971
  • 3
  • 21
  • 43
  • If we look at this from a slightly different direction, the [Liskov Substitution Principle](https://stackoverflow.com/questions/56860/what-is-an-example-of-the-liskov-substitution-principle), the problem stands out even more. If `StreeringWheel` inherited `Car`, then a `SteeringWheel` must be usable in all situations where a `Car` could be used. This is obviously nonsense. Moving back to the Asker's context, if `Node` Inherited from `List`, then `Node` and `List` must be interchangeable in all places where one would use a `List`. – user4581301 Nov 09 '18 at 23:37
  • @user4581301 good point! You might want to write your own answer instead of havocing mine ;p – Swordfish Nov 09 '18 at 23:42
  • Already on that. At the time I posted that comment, my answer was about 80% similar to yours. – user4581301 Nov 09 '18 at 23:48
  • @user4581301 Sorry for stealing your 80% then ;) What if i now steal 20% of yours? – Swordfish Nov 09 '18 at 23:48