meltedlilacs / ben

Bright Enough to Navigate
Other
0 stars 0 forks source link

better encapsulation with Node and List needed #5

Closed meltedlilacs closed 10 years ago

meltedlilacs commented 10 years ago

As it currently stands, calling List<T>::get() returns a pointer to a node object, on which Node<T>::getData() must then be called. I tried to fix this in Issue #4 , however, I forgot that List<T> 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<T>::getNode(), which would return a Node<T> pointer. The public List<T>::get() function could then return getNode()->getData().

Ideally we don't want the user to interact with the Node<T> class at all. So, we need to rewrite List<T>::add() to take a piece of data by value, then make a new Node<T> on the heap using the copied piece of data, also declared on the heap, then add it to the list.

metaporia commented 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.

meltedlilacs commented 10 years ago

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.

meltedlilacs commented 10 years ago

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