$ g++ lab_18.cpp sl_list.cpp
sl_list.cpp: In member function ‘std::string SLList::ToString() const’:
sl_list.cpp:60:13: error: assignment of member ‘SLList::head_’ in read-only object
head_ = head_->next_node();
^
Thankfully, your compiler has given you a meaningful message.
The line
head_ = head_->next_node();
is attempting to modify the state of your SLList object. Through the assignment operator, it will change what head_ contains. But your SLList::ToString() function has been declared as const, and ensures that it won't affect the state of the object. So you can see the conflict?
The SLList::ToString() const promises that the SLList will not change during the function and the compiler checks that the code of the function does not break that promise.
However, the code of the function attempts to change the this->head_. That is a blatant violation of constness.
Lets assume that you can change the head_ in the function. At the end of the function the SLList will have no clue about where all but the last node of the list are. That is bad, isn't it.
Lets look at the SLList::RemoveHead(). You call delete on the first node. The destructor of that node calls delete on the next node, whose destructor calls delete on the next node, whose ...
After the function the SLList still has non-zero size_ and the head_ points to node that has already been deleted.
In short, there are several details for you to pay attention to.