Closed meltedlilacs closed 10 years ago
I'm a little tired and incapable of intelligent thought, but that sounds good. Protecting nodes from the world at large should be a priority. Also wtf is a heap?
On Sat, Jul 5, 2014 at 9:51 AM, Gabriel Damon notifications@github.com wrote:
As it currently stands, calling List
::get() returns a pointer to a node object, on which Node ::getData() must then be called. I tried to fix this in Issue #4 https://github.com/GabrielD42/ben/issues/4 , however, I forgot that List must be able to access the Nodes in other functions. However, no one else should be able to. So I propose introducing a protected helper function List ::getNode(), which would return a Node pointer. The public List ::get() function could then return getNode()->getData(). Ideally we don't want the user to interact with the Node
class at all. So, we need to rewrite List ::add() to take a piece of data by value, then make a new Node on the heap using the copied piece of data, also declared on the heap, then add it to the list. — Reply to this email directly or view it on GitHub https://github.com/GabrielD42/ben/issues/5.
You'll get to it eventually in the book, but the heap allows the programmer to allocate (reserve) memory for use. Normally when you go out of scope (return from a function, for example), all variables and objects you created are deleted. However, with the heap, nothing is deleted until you specifically tell it to be. You have to be careful with the heap, though, because if you forget to delete objects they will take up memory that's difficult to recover.
So when you add a new item to the object, a new Node<T>
will be allocated from the heap. That way, even though you created it in one of List<T>
's functions, it sticks around the lifetime of the list.
To help remove heap appropriated objects, C++ provides the complement of a constructor, the destructor. The destructor is called when an object is deleted, giving the programmer time to reclaim memory. The class ClassName
would declare the destructor ~ClassName() {}
. The destructor can never take any parameters.
Another thing to be aware of when using the heap, or just pointers in general, is deep copy vs shallow copy. If an object has a pointer to data A
, if a copy of the object is created, ie object1 = object2
, or by passing it as a parameter, normally only the values of variables are copied, meaning both object1
and object2
have a pointer to the same object. This can lead to difficult to find errors if object1
changes the value of what it points to, since it will also change what object2
points to.
To fix this, C++ allows the programmer to define a copy constructor as well as overload the assignment operator (=). The copy constructor is called when an object is passed as a parameter and copying is done. The copy constructor is defined as ClassName(const ClassName& other) {}
, and the assignment operator ClassName& operator=(const ClassName& other) {}
. I usually have both these functions call a private helper function, as the only difference between them is the return value.
This private member function should copy what each pointer points to by getting the value and storing it a second time on the heap, allowing object1
and object2
to have different copies of what they point to.
That book will cover this better than I can. I haven't actually defined the copy constructors, assignment operators, and destructors for any of the classes, because I don't want to (its pretty tedious), but I can get away with it for now since I haven't done any copying yet.
After a lot of work, I think I have fixed the problem. List and its descendants can now be set to either delete their own data or leave it. Square chooses to make a list of the latter type. This allows Grid to be able to manage Squares and Square to add Squares to a list
As it currently stands, calling
List<T>::get()
returns a pointer to a node object, on whichNode<T>::getData()
must then be called. I tried to fix this in Issue #4 , however, I forgot thatList<T>
must be able to access theNode
s in other functions. However, no one else should be able to. So I propose introducing a protected helper functionList<T>::getNode()
, which would return aNode<T>
pointer. The publicList<T>::get()
function could then returngetNode()->getData()
.Ideally we don't want the user to interact with the
Node<T>
class at all. So, we need to rewriteList<T>::add()
to take a piece of data by value, then make a newNode<T>
on the heap using the copied piece of data, also declared on the heap, then add it to the list.