A smart pointer that directs screenptr to scrptr to control basic objects.
ScreenPtr(Screen *p): ptr(new ScrPtr(p)) {}
Unreference and arrow operations
Screenoperator*(){return *ptr->sp;}Screen*operator->(){return ptr->sp;}
There are two minor defects: the first is the undefined const version, and the second is the returned non-referenced, returned copy. In this way, one more copy operation is performed each time.
The necessity of const also deepens the impression, the first defect:
Screenptr PS (new screen (4, 4); const screenptr PS2 (new screen (3, 3); // The const type is easy to appear and must be compatible, non-const doesn't matter STD: cout <(* PS ). get () <":" <ps-> get () <STD: Endl; // STD: cout <(* PS2 ). get () <":" <PS2-> get () <STD: Endl; // failed, therefore, you must have a const version (only a few verification attempts are required )}
Verify the second small defect. The modification is invalid because it returns a copy instead of a reference.
std::cout << (*ps).getTest() << std::endl;(*ps).setTest(3);std::cout << (*ps).getTest() << std::endl;
Correct statement: const overload, operator * returns reference
public:Screen&operator*(){return *ptr->sp;}Screen*operator->(){return ptr->sp;}const Screen&operator*() const{return *ptr->sp;}const Screen*operator->() const{return ptr->sp;}
Return reference to facilitate modification (reduce the resource consumption of replication), and return const to avoid modification (also to allow the const object to be passed in )....
All are member functions, and operator * does not explicitly form parameters (If yes, should we mix it with multiplication?)
, Operator-> do not receive explicit parameters (the left operand is the object, and the right operand is the member name)
Arrow operators are special.
For point-> action ()
// If the point is a pointer, obtain the action Member of the Class Object pointed to by the pointer (that is, similar to the previous commonly used (& pair1)-> first, this-> price ;)
If (point is an object & Custom arrow operator ){
Point. Operator-> ()-> action; // It is equivalent to the action member after the point call-> operation.
If (point. Operator-> () does not return an object that contains action members)
Abolished;
Else
Continue to execute-> to read the action Member
}
Class Point {public: int action () {return 1;} Point * // reference operator-> () {STD :: cout <"call operator->" <STD: Endl; return PTR;} Point * PTR; private :}; int main () {point; point * PTR = & point; STD: cout <point. action () <STD: Endl; STD: cout <PTR-> action () <STD: Endl; // when PTR is a pointer, STD :: cout <(point. operator-> ()-> action () <STD: Endl ;//Point. Operator-> () is used to obtain a pointer (equivalent & point), and then the pointer corresponds to the-> member.STD: cout <(& Point)-> action () <STD: Endl; // This also limits the return type of the overloaded arrow operator to be point * type STD: cout <(point-> action () <STD: Endl ;}
Pe14_21.cpp
There are several key points: four classes are serialized through pointers. Note that both the lower and higher layers must provide the friend function to the upper layers, because the users who want to access
In addition, if all arrows are defined, an arrow is equivalent to a string of arrows.
Multi-layer structure judgment Condition
Two-layer pointers share only one layer of pointers.
Recursive destructor, counting, and hierarchy.
// Define a class, save a pointer to screen_ptr, and reload the arrow operator // defines a strict sequence to ensure the counting and analysis from top to bottom, however, the difference is that the screenptrptr initialization of the screenptr object allows two layers of objects to share a counter // There is also a small bug, using -- use = 0 in the recursion process to judge, as a result, the actual use is reduced to a smaller value than 0, because of the unsigned type, direct overflow, abnormal judgment, the use ofShort circuit orTo determine //Do not leave a tail. Additional operations for testing must be commented out., Like: delete ptrptr; Delete PTR; this double structure # include "head. H" Class Screen {public :~ Screen () {STD: cout <"calling ~ Screen ().... "<STD: Endl;} typedef STD: String: size_type index; // use typedef char get () const {// return contents [cursor]; return 'T'; // test} // reload void settest (index I) {cursor = I;} index gettest () {return cursor;} inline char get (index HT, index WD) const; // explicitly defines inline index get_cursor () const; // the latter is easy to read, and the declaration in class definition is clear void set_height (index I) {Height = I;} index get_height () const {return height;} publi C: screen (index HT, index WD): height (HT), width (WD) {} PRIVATE: STD: String contents; index cursor; // cursor index height, width; // multiple declarations at the same time}; Class scrptr {public: // to test the establishment of a scrptr object friend class screenptr; friend class screenptrptr; screen * sp; size_t use; scrptr (screen * P): SP (P), use (1 ){}~ Scrptr () {If (use = 0 | -- use = 0) {STD: cout <"calling ~ Scrptr ().... "<STD: Endl; Delete SP ;}}; class screenptr {friend class screenptrptr; public: screenptr (screen * P): PTR (New scrptr (p )) {} screenptr (const screenptr & orig): PTR (orig. PTR) {++ PTR-> use ;}~ Screenptr () {If (PTR-> Use = 0 | -- PTR-> Use = 0) {STD: cout <"calling ~ Screenptr ().... "<STD: Endl; Delete PTR;} STD: cout <" PTR-> Use: "<PTR-> use <STD: Endl ;} public: void display () {} public: screen & operator * () {return * PTR-> sp;} screen * operator-> () {return PTR-> sp ;} const screen & operator * () const {return * PTR-> sp;} const screen * operator-> () const {return PTR-> sp ;} screenptr & operator = (const screenptr & RHs); Private: scrptr * PTR;}; Class screenptrptr {// I will not change it Screenptr: public: screenptrptr (screen * P): ptrptr (New screenptr (p) {} screenptrptr (const screenptrptr & orig): ptrptr (orig. ptrptr) {++ ptrptr-> PTR-> use;} screenptrptr (const screenptr & orig): ptrptr (& orig) {++ ptrptr-> PTR-> use ;}~ Screenptrptr () {If (ptrptr-> PTR-> Use = 0 | -- ptrptr-> PTR-> Use = 0) {STD: cout <"calling ~ Screenptrptr ().... "<STD: Endl; Delete ptrptr;} public: void display () {} public: scrptr * operator-> () {return ptrptr-> PTR ;} const scrptr * operator-> () const {return ptrptr-> PTR;} screenptrptr & operator = (const screenptrptr & RHs) {RHS. ptrptr-> PTR-> Use ++; ptrptr-> PTR-> sp = RHS. ptrptr-> PTR-> sp; return * This;} PRIVATE: const screenptr * ptrptr; // to facilitate the definition of the last constructor}; char screen :: get (Index R, index C) cons T {index ROW = r * width; return contents [row + C];} inline screen: Index screen: get_cursor () const {return cursor;} screenptr & screenptr :: operator = (const screenptr & RHs) {RHS. PTR-> Use ++; PTR-> sp = RHS. PTR-> sp; return * This;} int main () {screenptrptr P (new screen (4, 4); // an destructor STD :: cout <"================" <STD: Endl; screenptrptr P2 (P ); // P2 and P1 will last destroyed and will call a screenptr destructor (in fact it is useless) screenptr P3 (New Screen (3, 3); // execute the three destructor scrptr P4 (new screen (2, 2) in sequence; // perform two sequential analyses/* STD:: cout <p-> SP-> get_height () <STD: Endl; // test the arrow equivalence relationship (I changed it, you can add more grass-roots arrows) STD :: cout <p. operator-> ()-> SP-> get_height () <STD: Endl; // Why is this sentence not recognized? After being silly for half a day, there are more than half of the brackets STD: cout <(p3.operator-> ()-> get_height () <STD: Endl; STD :: cout <(p4.sp-> get_height () <STD: Endl; screenptrptr P5 (new screen (1, 1); screenptrptr P6 (new screen (1, 1); P5 = P; P6 = P5; // test cross-layer common count. disadvantage: the upper layer must be initialized with a lower-layer object. The order is incorrect, unable to call the screenptrptr destructor screenptr P (new screen (4, 4); screenptr P2 (p); screenptrptr pp (p); screenptrptr PP2 (new screen (3, (3); // The deletion order is different because of the different levels and the different levels. The recursive analysis structure of public count cannot be used, I will take a look back later */}