Tuesday, November 28, 2017

Yet Another Chapter Summary

This was one long road to reach the end of this first chapter about classes in C++! It has taken the better part of three months to get there, and it wasn't an easy journey. 

The main chapter was rather easy to follow, and for the first time I managed to answer all Quiz-questions correctly and having been able to solve the Exercise section without major trouble, I felt well prepared for the Programming Challenges section.

When I began with the first Challenge, it is about writing a Date class, the trouble began. While conceptually being able to work it out, and having solved a similar problem with structures, the great difficulty for me was to translate it all to a class with the setters and getters and constructor and what else a class consists of.

The main difficulty was to work out a way to write such a class, and what the getters and setters actually do, I could not readily understand this. It took two days until I managed to translate something into code that would work, and another six or seven to solve it. Getting past this first challenge, the second, the third, and numerous others felt equally as difficult as the first one.

It wasn't until challenge 13.14 that writing a classes header and implementation files became less difficult. Slowly I began to understand how everything has to go together to form one unity. This doesn't mean that it was done correctly, just that things were working, the output was correct, there were no crashes or other problems of that nature. I also started noticing how much more convenient it is to work with classes. Being able to write code for a sub-set of a bigger problem, testing it in isolation to see if it works, then keep doing the same for another sub-set of the problem until the big problem is solved is a huge advantage. If one part does not fit in the big picture, instead of having to start all over, there is only this function that needs to be changed. Eventually I became a bit more comfortobale working with one or two class files up to that point in time. 

As you will notice, past a certain point I started working with more than one class and implementation file. The first time was for the Cash Register challenge, it contains three header and two implementation files. Now, as you might expect, this working with many class files brought about a new set of problems. How to get those seperate entities to work together?

Having particular ideas what each should do was one thing, they don't behave any differently to what has come before. If everything works in isolation, putting it all together in the driver should be no problem. In fact, it isn't, if you know how, which I didn't at that point. Below is my thought process:

"Well, wouldn't it be great if a member variable or a function inside one class could be used in another?", "Of course! But how?", "Why don't you put the #include "classOne.h" into the "classTwo.h" file, and see what it does?", "Great! Let's do it!"

But, but, but, where is there a problem with that? The problem starts when this person learns that this does indeed work. 

"So, if this works, wouldn't it also be great to find a possibility to work with two or more classes in such way, that they update each other?", "Yes, yes, yes! This is what is needed for the current challenge!"

This idea and thought process came about while working on the "A Game of 21" challenge. The idea was to have the game, menu and player class a way of sharing a players' information. The game class had a player object and dice object in it, and I saw the need to have the game and menu class both get that name. When I tried linking menu and game class in a way such that the one contains an include of the other, was the point that I learned the hard way about 'Circular dependencies.'

Consider this example:

#include "cTwo"

class cOne
{
   // ........
}

#include "cOne"

class cTwo
{
   // .........
}

This is the way it was, and it became clear that it wouldn't work. Let me explain in a little more detail why I saw the need of a construct like this. One file had a player object, and via call this player objects' name variable would be set. Yet, when trying to retrieve the players' name from outside the class, or within the menu class, the name returned empty. You can imagine the reason why this is so. Because the player object was instantiated game class local, there is no way of another class to even know about the existence of it, much less what it might contain in terms of data. 

Consider this:

The game class contains a player object.
The game class makes a call to a player class function that sets the players' name.
The game class now has a name for the player, and can make another call to a function that returns this players' name.

The menu class, for instance, if it contains an include of the player class, if it accesses the getPlayerName() function, what does it get? An empty string. There doesn't exist any data for the menu class retrievable from the player class. The idea of working around it was to set the variable to holding the name to static, which, in itself, was causing another problem entirely. In the end I gave up on the idea and started looking for a better way to write the classes.

Such and other problems were keeping me busy for a very long time. In the end I do feel that a great number of challenges could have been solved in a better way than I was able to do it. Yet, I have also learned many new things, and I do feel alot more confident working with classes. I just hope that the next chapter and its challenges will be a lot easier now that I have a basic grasp of things.

With this, it is time to move on to another chapter, and soon enough, time to solve more programming challenges. To my visitors regular and new, thank you for coming by! And to my fellow students, well, I hope you have had an easier start with classes than me, and that you are also able to move on to the next chapter soon, if you are still working on the challenges. Keep it up, never give up! 頑張ってね!

No comments:

Post a Comment