Making a copy constructor more flexible for ADT queue
Remove redundancy


   {
    Node* saveFirst;
    Node* walker;
    first = other.first;
    walker = new Node(first-&gt;data);
    saveFirst = walker;
    while (first-&gt;next != nullptr)
    {
        walker-&gt;next = new Node(first-&gt;next-&gt;data);
        walker = walker-&gt;next;
        first = first-&gt;next;
    }
    walker-&gt;next = nullptr;
    first = saveFirst;
    }
this-&gt;nrOfElements = other.nrOfElements;



You create a temporary variable saveFirst.  You then use a class field as temporary variable.  When done, you set the class field to the value set in the temporary variable.  Why not do it the other way around?  

   {
       Node* current = new Node(other.first-&gt;data);
       first = current;

       for (Node *otherCurrent = other.first; otherCurrent-&gt;next != nullptr; otherCurrent = otherCurrent-&gt;next)
       {
           current-&gt;next = new Node(otherCurrent-&gt;next-&gt;data);
           current = current-&gt;next;
       }

       current-&gt;next = nullptr;
       nrOfElements = other.nrOfElements;
    }


This uses the temporary variable to hold the changing current variable.  It sets first to the correct value immediately and directly.  It changes the loop to say for every node in other.  Now you don't have to set the class field at the end.  

Note that I also moved the number of elements assignment inside the else.  In the original it would have tried to dereference a null other.  

Reuse other methods

You don't mention other functions in the class, but there are certain ones that could be used here (assuming C++11).  

    {
        for (auto i : other)
        {
            this.append(i.data);
        }
    }


This would replace the entire else block.  If you have to create the begin, end, and append functions anyway, then this drops the amount of code that you have to maintain considerably.  Note that begin and end are required to make the range-based for loop work.