.. (לתיקייה המכילה) | ||
I use VC++; while using the STL classes I get tons of annoying warnings. What am I doing wrong? | |
Probably nothing. Add the following line to BalanceBook.h (which is included by all files): #pragma warning ( disable : 4786) |
Can we create a similar class to BBEntry that will be used outside BalanceBookList? | |
No. any type that packs both an expense type and an amount of money is considered as "similar" in that case! |
Do we have to worry about proper garbage collection? | |
Not in this assignment. I mean - don't leave allocated memory undeleted on purpose, but don't try too hard to find a way to free memory if you can't do it easily. |
What do you mean by the line | |
I mean: create an operator += that will either add a new expense type (named "cellular") with the amount of 223, or if such entry already exists, it will add the amount of 223 to the existing amount. And no, you are still not allowed to add a BBEntry-like type :-); think of a good alternative. |
Is there such syntax as | |
Not that I know of. |
Operator overloading is about readability and self-documentation of code (and to quote the coding guidelines: "Your code should be as readable as possible. In most cases, readability = simplicity"), but code such as "february -= january;" or "february -= "water";" is not easily understandable. There is a fine line between proper overloading, and abuse. This, in my opinion, has left that line far behind... | |
While I agree with you that some of the operations in the pseudo-code are close to operators-abuse as you phrased it, I think most of them are not. I do agree that something like "february -= january;" is a bit peculiar but it does not cross the line of total nonsense in my opinion. For instance: assume that you use this class for management of expenses and you keep a BalanceBook object for every month; now assume that the user would like fix something in one of the months; don't you think it would be comfortable to use such operator to remove the chosen month from, say, the annual balance it belongs to and then use the += operator to add it back after it was fixed? I think such operator can be useful. Also the "february -= "water";" is useful in my opinion too and also makes sense (but maybe this is because I've written several such assignments :-). Anyways - I tried to collect the most reasonable operators I could think of and put them in the example; I don't think there are too many other operators you could use in this case, and I don't expect you to implement operators you think are unreasonable (unless they are given in the example...). |
Line 23 of the pseudo code : Shouldn't it be BalanceBook::const_iterator& so that all the methods of the const_iterator, which should be virtual, will be activated dynamically? | |
Excellent point! This was fixed in version 1.02 of the assignment. Note that this means that both begin() and end() will dynamically allocate iterators const_iterators that need to be freed later. Also - we do not want to grant the user of the iterators with the responsibility of doing this. Could you think of a solution? One possible solution for this problem is to define a smart pointer for the iterators, which will free the iterators when it dies. You can read about smart pointers here: http://ootips.org/yonat/4dev/smart-pointers.html . There is another simpler solution, but the smart pointer one is much nicer. You won't lose points for choosing the simpler solution, but you will learn much more from using smart pointers. this is not very hard to understand (I think) and it is very useful for real-life programming. |
Can we change the type of BalanceBook::const_iterator& in line 23 if we use smart pointers? | |
Of course! |
What does this line mean: | |
This is the same as january += {"food", 1253}; The << operator means "put to"; in this example - put {"food", 1253} to january. |
Suppose I have a class V that is abstract from which two classes inherit, D1 and D2. Now, I would like to define a comparison operator for the whole tree; best thing I can do is to define it as | |
In that case, it is important to know in the operator == the exact type of the argument. Now the solution here depends a lot on the problem at hand. I assume you refer to the problem of implementing the operator == for the tree of iterators: in that case, best thing I could think of is to use dynamic_cast for this purpose. This is what I'd do: - Note that BalanceBookList::iterator is comparable with another BalanceBookList::iterator only (same is true for the map side). In your BalanceBookList::iterator's overriding of == (same for BalanceBookMap::iterator) - Use dynamic_cast to convert the argument to the exact type of the class - In case you get NULL, immediately return false - Otherwise - use the pointer for performing the comparison. In general, we do not want to rely upon exact type of an object since this contradicts the idea of polymorphism ("talk" to the interface only, avoid knowing the exact type). This case is an exceptional since - We do not give a special treatment to any other type except ours; knowing that the type of the argument is not of the same type as ours gives us the value we need to return (false) - We do not rely upon any other type except ours, which means that we can add as many other implementations as we want without having to modify existing implementations. |
What functions should be implemented in the iterators? | |
Implement a minimal set of operations that will enable your iterators work correctly (e.g. the operators ++ and --, operations expense() and amount()). Don't waste time on a huge interface with many operations. |
[BUG FIX] | |
You are correct, this should actually be iterator rather than const_iterator. iterator should be used for non-const BalanceBooks, while const_iterator should be used for const BalanceBooks; both iterators should not be used for modifying the objects, but just for "observing" their contents; any modification should be performed via BalanceBook's functions and operators (e.g. operator []) |
While using dynamic_cast in VC++ I get a warning; what should I do? | |
This is probably caused because run-time type information is disabled; do the following: In project->settings->C/C++ tab, mark a V in "Enable Run-Time Type Information (RTTI)". This should solve the problem. |
Do we have to take care of errors using exceptions? | |
Basically yes; you should use exceptions whenever you detect an error you can't handle by yourselves in the code. Although you can write your own exception classes, we strongly recommend that you take a look at STL's classes for handling exceptions; look for the class exception and its descendents and use them (or inherit from them) whenever you can. It will save you time. |
If we can't modify the non-const BalanceBook via the non-const iterator, what do we need it for? why can't we just have the const_iterator version? | |
the (non const) iterator can be used in case you want to change the contents of its object, via functions of BalanceBook, while the const_iterator can't. For instance: suppose you supply a function named erase() that accepts an iterator, and deletes the corresponding entry: class BalanceBook { ... iterator erase(iterator it); // Delete the entry pointed by it, make it point to the next object ... }; In this case - you use iterator (and not const_iterator) as an argument for erase(). Obviously, this can be done in objects that are not const only. You can also make iterator's amount() and expense() return references, but I think you might encounter some problems in the BalanceBookMap version, so you don't have to do this. Implement at least this erase() function, just to show that it works. |
objects of type auto_ptr<T> lose the object they keep after using the assignment opertor, or the copy constructor; for instance - | |
Yes; I did not find anywhere the assignment in where this is a problem. |