I am currently trying to eliminate the use of char * within my project in favour of having my own string class.
I have made notes in the header and source code of the errors. I have several issues/questions I need to resolve. Operator overloading is new to me, but I hope to understand this better as I also want to improve other classes like vmSize and vmPoint.
The issues/questions are:
Q1. Why do we need to make a forward declaration of the class ostream?
Q2. Why can't the overloaded << operator access the private data member char *m_pchStr when it's a friend of the vmString class?
Q3. Where should the overloaded (friend) << operator go within the class definition, and does it matter?
Q4. Within the destructor, should I set m_pchStr to NULL or 0 after delete?
Q5. Can the copy constructor go into an infinite loop? How to prevent?
Q6. How can I change std::cout << &testStr << std::endl; so that I do not have to proceed the variable with & ?
Q7. Should I use exception handling within AllocString() instead of assert()?
Q8. Does a string literal automatically append a null terminator at the end?
Code:#ifndef __VMSTRING_H__ #define __VMSTRING_H__ #include <iostream> class ostream; // Why needed - error: 'ostream' does not name a type namespace vmStd { class vmString { friend ostream &operator<<(ostream &output, const vmString &str); public: vmString(const char *str = ""); vmString(const vmString &cpy); ~vmString(); int length() const { return m_nLength; } private: void AllocString(const char *str); int m_nLength; char *m_pchStr; // error: char* vmStd::vmString::m_pchStr' is private }; } // namespace vmStd #endif // __VMSTRING_H__Code:#include <cstring> #include <cassert> #include "vmString.h" using namespace vmStd; //----------------------------------------------------------------------------- // FN/Method: vmString(const char * = "") // Description: vmString class constructor. Converts char * to a vmString // object. //----------------------------------------------------------------------------- vmString::vmString(const char *str) : m_nLength(strlen(str)), m_pchStr(0) { AllocString(str); } //----------------------------------------------------------------------------- // FN/Method: vmString(const vmString &) // Description: vmString class copy constructor //----------------------------------------------------------------------------- vmString::vmString(const vmString &cpy) : m_nLength(cpy.m_nLength) { AllocString(cpy.m_pchStr); } //----------------------------------------------------------------------------- // FN/Method: ~vmString() // Description: vmString class destructor //----------------------------------------------------------------------------- vmString::~vmString() { delete [] m_pchStr; } //----------------------------------------------------------------------------- // FN/Method: AllocString(const char *) // Description: Dynamically allocate memory for new vmString object //----------------------------------------------------------------------------- void vmString::AllocString(const char *str) { m_pchStr = new char[m_nLength + 1]; // Allocate storage assert(m_pchStr != 0); // Terminate if memory not allocated strcpy(m_pchStr, str); // Copy literal to vmString object } //----------------------------------------------------------------------------- // FN/Method: ostream &operator<<(ostream &, const vmString &) // Description: Allow the output of a vmString object //----------------------------------------------------------------------------- ostream &operator<<(ostream &output, const vmString &str) { output << str.m_pchStr; // error: within this context ??? return output; // Enables cascading }Code:#include <iostream> #include "vmString.h" using namespace vmStd; int main() { // One part construction vmString testStr = "Hello string"; std::cout << &testStr << std::endl; return 0; }




Reply With Quote
