Quote:Original post by Intrigue7
Quote:
Anyway, while I'm on this step, I'm going to fix up some names to be a little more consistent, mostly by getting rid of the useless Hungarian notation. The C++ type system is much stronger than C's, and it wants to help you; let it.
I'm a C programmer and I am wondering why you consider Hungarian notation as useless.. It intrigued me so I started to dig more info on google and everyone seems to agree with you... But... I still do not know why.. lol. I'd appreciate a small clarification on this. Also, what do you mean by C++ type system wants to help you ?
The primary reason you don't understand this is because you are a C programmer. :) The basic idea is that the whole point of having a type system is to catch type errors; otherwise, it is getting in your way. The idea with Hungarian notation is to supplement the "physical" type of a variable (the one the compiler understands) with a "logical" one (as indicated by the prefix). This loses the benefit of "the compiler understands", and comes at the expense of making humans do extra work to think about these cryptic prefixes.
In C++, we can create new types easily. Consider, for example, Joel Spolsky's example with "safe" and "unsafe" strings. Granted, his example is for PHP, which is dynamically typed. (I've often wanted to do Hungarian notation in my Python code, but it seems that some combination of unit testing and explicit type checking works much better.)
All we do is create the "safe string" type, by making a structure and writing the relevant functionality. Unsafe strings can continue to be represented with std::string. By requiring explicit conversions from unsafe -> safe, we cannot use an unsafe string without "escaping" it.
class SafeString { std::string data; explicit SafeString(const std::string& unsafe); // does the escaping logic. public: // The concatenation of two SafeStrings is always safe. SafeString& operator+=(const SafeString& ss) { data += ss.data; return *this; } SafeString operator+(const SafeString& ss) { return SafeString(*this) += ss; } // We can't modify a SafeString's characters directly, because we could // inject an unsafe character. But we can read them: char operator[](size_t index) const { return data[index]; } friend ostream& operator<<(ostream& os, const SafeString& ss) { return os << data; } // etc. etc. // Force clients to use a named function instead of a constructor, to make it // clear what is going on. This, strictly speaking, probably isn't necessary. friend SafeString escape(const std::string& unsafe) { return SafeString(unsafe); } std::string unescape() { return data; } // makes an "unsafe" copy.};