/************************************************************************/ /* strngbad.h __ flawed(缺点) string class definition */ /************************************************************************/ #include <iostream> #ifndef STRNGBAD_H_ #define STRNGBAD_H_ class StringBad { private: char * str; // pointer to string int len; // length of string static int num_strings; public: StringBad (const char * s); // constructor StringBad(); // default constructor ~StringBad(); // destructor // friend function friend std::ostream & operator << (std::ostream & os, const StringBad & st); }; #endif
/* Notes: 1)you cannot initalize a static member variable inside the class declaration. That's becase the declaration is a description of how memory is to be allocated but it doesn't allocate memory. 2)In the case of a static class member, you initialize the static member independently, with a separate state-ment outside the class declaration. That's because the staic class member is stored separately tather than as part of an object. 3)This initializetion goes in the methods file, not in the class declaration file. That would result in multiple copies of the initialization statement, which is an error. */ // strngbad.cpp -- StringBad class methods #include <cstring> // string.h for some #include "strngbad.h" using std::cout; // initializing static class member int StringBad::num_strings = 0; // class methods // construct StringBad from C string StringBad::StringBad(const char * s) { len = std::strlen(s); // set size str = new char[len + 1]; // allot storage std::strcpy(str, s); // initialize pointer num_strings++; // set object count cout << num_strings << ": \"" << str << "\" object created \n "; // For Your Information } StringBad::StringBad() // default constructor { len = 4; str = new char[4]; std::strcpy(str, "c++"); // default string num_strings++; cout << num_strings << ":\" "<< str << "\" default object created\n"; // FYI } StringBad::~StringBad() // necessary destructor { cout << "\" "<< str << "\" object deleted, "; -- num_strings; // required cout << num_strings << " left \n"; delete [] str; // required } std::ostream & operator << (std::ostream & os, const StringBad & st) { os << st.str; return os; }
/************************************************************************/ /* 1、vegnews.cpp -- using new and delete with classes 2、remember: The problems with the StringBad class stem from implicit member functions that are defined automatically and whose behavior is inappropriate to this particular class design. stem [stem] n. 干; automatically [,ɔ:tə'mætikəli] adv. 自动地;机械地;无意识地 behavior [bi'heivjə] n. 行为,举止;态度;反应 inappropriate [,inə'prəupriət] adj. 不适当的;不相称的 particular [pə'tikjulə] adj. 特别的;详细的;独有的;挑剔的 3、C++ automatically provides the following memeber functions: 1)A default constructor if you define no constructors 2)A copy constructor if you don't define one 3)An assignment operator if you don't define one ( 赋值操作符) assignment [ə'sainmənt] n. 分配;任务;作业;功课 operator ['ɔpəreitə] n. 经营者;操作员;话务员;行家 4)A default destructor if you don't define one 5)An address operator if you don't define one(地址操作符) */ /************************************************************************/ #include <iostream> using std::cout; #include "strngbad.h" void callme1(StringBad &); // pass by reference(按引用传递) void callme2(StringBad); // pass by value(按值传递) int main() { using std::endl; // create three StringBad objects StringBad headline1("Celery Stalks at Midnight"); StringBad headline2("Lettuce Prey"); StringBad sports("Spinach Leaves Bowl for Dollars"); cout << "headlines1: " << headline1 << endl; cout << "headlines2: " << headline2 << endl; cout << "sports: " << sports << endl; // passes handline1 to the callme1()function callme1(headline1); cout << "headlines1: " << headline1 << endl; callme2(headline2); cout << "headlines2: " << headline2 << endl; cout << "Initialize one object to another: \n"; StringBad sailor = sports; cout << "sailor: " << sailor << endl; cout << "Assign one object to another: \n"; StringBad knot; knot = headline1; cout << "knot: " << knot << endl; cout << "End of main() \n"; return 0; } void callme1(StringBad & rsb) { cout << "String passed by reference: \n"; cout << " \" "<< rsb << "\"\n"; } void callme2(StringBad sb) { cout << "String passed by value: \n"; cout << " \" "<< sb << "\"\n"; }