From dd0127d725d2aba3c81e502d4ae03a14e5f2eef9 Mon Sep 17 00:00:00 2001 From: Kamil Kaminski Date: Fri, 28 Feb 2014 03:55:14 -0600 Subject: clarify obj creation, declare static field for.... counting, introduce outward conversion to 'const char *' without a copy, implement != operator --- main.cpp | 18 +++++++++++++++--- string.cpp | 61 +++++++++++++++++++++++++++++++++++++++---------------------- string.h | 27 +++++++++++++++++++-------- 3 files changed, 73 insertions(+), 33 deletions(-) diff --git a/main.cpp b/main.cpp index dd4810d..607b40c 100644 --- a/main.cpp +++ b/main.cpp @@ -10,9 +10,13 @@ int main(int argc, char **argv) else std::cout << "false" << std::endl; + /* uses copy ctor, compiler implicitly creates obj out of ", beta" and + * then passess it to copy ctor + */ MyString mystr1 = ", beta"; - MyString mystr2 = ", charlie"; - MyString mystr3 = ", delta"; + /* next to call ctor that takes in char arr */ + MyString mystr2("charlie"); /* if it was () then it would be a fwd decl! */ + MyString mystr3 = MyString(", delta"); mystr.concat(mystr1).concat(mystr2).concat(mystr3); std::cout << mystr << std::endl; @@ -21,9 +25,17 @@ int main(int argc, char **argv) mystr4.concat(", world!").concat(" goodbye"); std::cout << mystr4 << std::endl; + /* test outward conversion */ + const char *mystr_charptr = mystr4; + std::cout << mystr_charptr << " | len: " << std::strlen(mystr_charptr) << std::endl; + MyString mystr5 = "bro"; std::cout << mystr5 << ", char at 1 is: " << mystr5[1] << std::endl; + /* getCount() is a static method hence it doesn't need to be called on + * an object + */ + std::cout << "mystring instances count: " << MyString::getCount(); + return 0; } - diff --git a/string.cpp b/string.cpp index 42e97cc..e75b50e 100644 --- a/string.cpp +++ b/string.cpp @@ -9,23 +9,41 @@ MyString::MyString(int len) : str_(new char[len + 1]), length_(len) { + this->count++; } -MyString::MyString(const char *str) : length_(strlen(str)) +MyString::MyString(const char *str) : str_(new char[strlen(str)+1]), length_(strlen(str)) { - str_ = new char[length_ + 1]; strcpy(str_, str); + this->count++; } MyString::MyString(const MyString& str) : str_(new char[str.length_ + 1]), length_(str.length_) { strcpy(str_, str.str_); + this->count++; +} + +MyString& MyString::operator=(const MyString& rhs) +{ + /* don't do anything if object assigns itself */ + if (this == &rhs) + return *this; + + length_ = rhs.length_; + delete[] str_; + str_ = new char[ length_ + 1]; + strcpy(str_, rhs.str_); + + /* assignment operator requires this */ + return *this; } MyString::~MyString() { delete[] str_; + this->count--; } int MyString::indexOf(char ch, int pos) const @@ -41,6 +59,9 @@ int MyString::indexOf(char ch, int pos) const return -1; } +/* define this field only once, .h is not the best place */ +size_t MyString::count = 0; + bool MyString::isSubstring(const MyString& str) const { if (length_ < str.length_) @@ -65,6 +86,9 @@ bool MyString::isSubstring(const MyString& str) const return false; } +/* might seem redundant since constructor can create an object from char array + * and call other isSubstring method that takes in MyString type + */ bool MyString::isSubstring(const char *str) const { int i, j, k; @@ -109,21 +133,6 @@ MyString& MyString::concat(const char *str) return *this; } -MyString& MyString::operator=(const MyString& rhs) -{ - /* don't do anything if object assigns itself */ - if (this == &rhs) - return *this; - - length_ = rhs.length_; - delete[] str_; - str_ = new char[ length_ + 1]; - strcpy(str_, rhs.str_); - - /* assignment operator requires this */ - return *this; -} - bool operator==(const MyString& lhs, const MyString& rhs) { if (lhs.length_ != rhs.length_) @@ -135,13 +144,17 @@ bool operator==(const MyString& lhs, const MyString& rhs) return false; } -/* seems like the ostream& in front has nothing to do with dereferencing a pointer, - * but it seems like the & is placed there so we can make consecutive overloaded - * calls to cout, effectively chaining all of the calls - */ +bool operator!=(const MyString& lhs, const MyString& rhs) +{ + return !(lhs == rhs); +} /* right now I think the reference is used to avoid returning copy of ostream - * so when calls are chained up we work on one ostream object only */ + * so when calls are chained up we work on one ostream object only + * + * this function is in global scope, it is friend'ed to allow us access to data + * members of calss MyString + */ std::ostream& operator<<(std::ostream& ostr, const MyString& rhs) { return (ostr << rhs.str_); @@ -179,3 +192,7 @@ MyString::operator char*() return NULL; } +MyString::operator const char*() const +{ + return this->str_; +} diff --git a/string.h b/string.h index dbc8e88..2e86086 100644 --- a/string.h +++ b/string.h @@ -17,11 +17,14 @@ class MyString char *str_; int length_; MyString(int); + static size_t count; public: MyString(); - MyString(char); + explicit MyString(char); + /* allow implicit conversions, it is useful */ MyString(const char *); + /* copy constructor */ MyString(const MyString &); MyString& operator=(const MyString &); ~MyString(); @@ -33,29 +36,33 @@ class MyString MyString& concat(const MyString &); MyString& concat(const char *); void printStr(void) const; + static size_t getCount(void); bool operator!(void) const; char& operator[](int); char operator[](int) const; operator char*(); /* outward class conversion into char * */ + operator const char*() const; }; bool operator==(const MyString&, const MyString &); +bool operator!=(const MyString&, const MyString &); std::ostream& operator<<(std::ostream&, const MyString &); -inline MyString::MyString() +/* it is always good idea to have default ctor to avoid manual init later + * for data types that include this class type + */ +inline MyString::MyString() : str_(new char[1]), length_(0) { - length_ = 0; - str_ = new char[1]; str_[0] = '\0'; + this->count++; } -inline MyString::MyString(char ch) +inline MyString::MyString(char ch) : str_(new char[2]), length_(1) { - length_ = 1; - str_ = new char[2]; str_[0] = ch; str_[1] = '\0'; + this->count++; } inline int MyString::length() const @@ -68,5 +75,9 @@ inline void MyString::printStr(void) const std::cout << "length: " << length_ << ", value: \"" << str_ << "\""; } -#endif +inline size_t MyString::getCount(void) +{ + return count; +} +#endif -- cgit v1.2.3