"C + + Programming thought" third chapter hidden implementation (exercise + answer)

Source: Internet
Author: User

I. Relevant knowledge points

1. In C + +, access control is not an object-oriented feature, but it provides valuable access control for the creators of the class. The user of the class can clearly see what can be used and what should be ignored. More importantly, it ensures that the user of the class does not rely on the implementation details of any class. With this, we can change the implementation of the class, and no one will be affected because they don't have access to this part of the class. Once we have the freedom to change the implementation section, we can improve our design in a later time and allow for mistakes. You know, no matter how carefully we plan and design, we can make mistakes. Knowing that making mistakes is also relatively safe means that we will become more experienced, learn faster, and finish the project sooner. The public interface portion of a class is visible to the user. Therefore, in the analysis and design phase, it is more important to ensure the correctness of the interface. This is not to say that interfaces cannot be modified. If we do not design the interface section correctly for the first time, we can add more functions so that we do not need to delete the program code that has used the class.

2. Visible Implementation Section
Some projects do not allow the end user to see their implementation part. For example, some policy information may be displayed in the header file of a library, but the company does not want this information to be obtained by competitors. For example, in a system that is very important for security (such as a cryptographic algorithm), we do not want to expose any clues in the file in case someone decodes our code. Maybe we put the library in a "hostile" environment where programmers are desperate to access our private members with pointers and type conversions. In all these cases, it is necessary to put a compiled actual structure in the implementation file instead of exposing it to the header file.

3. Handle class (handle classes)
Access control in C + + allows the implementation to be separated from the interface part, but the implementation is not completely hidden. The compiler must know the declaration of all parts of an object so that it can be created and managed. We can imagine a programming language that simply declares the part of the public interface of an object, and hides the private implementation part. However, C + + will do as much static type checking as possible during compilation. This means catching errors early and also means that the program is more efficient. This, however, has two implications for private implementations: first, even if the programmer cannot easily access the implementation section, he can see it, and the second is to create unnecessary repetitive compilations.

Two. Related code

1.

#include <iostream>using namespace std;/*public.cpp*/struct a{int i;char j;float f;void foo ();}; void A::foo () {}struct b{public:int i;char j;float f;void foo ();}; void B::foo () {}int main () {return 0;}

2.

#include <iostream>using namespace std;/*private.cpp*/struct b{private:char j;float f;public:int i;void foo ();}; void B::foo () {i = 0;j = ' 0 '; f = 0.0;} int main () {B B;B.I = 1;//ok public//b.j = ' 1 '; illegal,private//b.f = 1.0;illegal,privatereturn 0;}


3. Protection (Protected)
The last access specifier is protected. Protected is basically similar to private, with only one difference: inherited structures can access protected members, but private members cannot be accessed


4.

#include <iostream>using namespace std;/*friend.cpp*/struct x;struct y         //struct y must be declared as a struct in its member Y:: F (x*) x                 //A friend is declared before, but Y:: F (x*) to be declared, struct X must first declare {void F (x*);}; struct X{private:int i;public:void initialize (); friend void G (x*, int); friend void Y::f (x*); friend struct Z;//friend Stru CT Z is an incomplete type description, and the entire struct is treated as a friend. friend void H ();}; void X::initialize () {i = 0;} void G (x* X, int i) {x->i = i;} void Y::f (x* X) {x->i = 47;} struct Z{private:int j;public:void initialize (); void g (x* X);}; void Z::initialize () {j = 99;} void Z::g (x* X) {x->i + = j;} void H () {X x;x.i = 100;} int main () {x x; Z Z;Z.G (&x); return 0;}


5.

#include <iostream>using namespace std;/*nestfrnd.cpp*/#include <string.h> #define SZ 20/*struct The holder contains an integer array and a P-ointer, which we can access by pointer. Because pointer is closely linked to Holder, it is necessary to use it as a member of a struct. Once pointer is defined, it can gain access to the private members of the holder by using the following declaration: Friend Holder::p Ointer; Note that the struct keyword is not required because the compiler already knows what pointer is. struct Holder{private:int A[sz];p ublic:void Initialize (); struct pointer{private:holder* h;int* p;public:void Initialize (holder* H); void next (), void previous (); void top (); void end (); int read (); void set (int i);}; Friend Holder::p Ointer;}; void Holder::initialize () {memset (a,0,sz*sizeof (int));} void Holder::p ointer::initialize (holder* h) {h = h;p = H->a;} void Holder::p ointer::next () {if (P < & (H->a[sz-1])) {p++;}} void Holder::p ointer::p revious () {if (P > & (H->a[0])) {p--;}} void Holder::p ointer::top () {p = & (H->a[0]);} void Holder::p ointer::end () {p = & (H->a[sz-1]);} int holder::p ointer::read () {return *p;} void Holder::p ointer::set (int i) {*p = i;} int main () {Holder H;holder::p ointer hp,hp2;int i;h.initialize (); hp.initialize (&h); hp2.initialize (&h); for (i = 0;i < SZ ; ++i) {hp.set (i); Hp.next ();} Hp.top (); Hp2.end (); for (i = 0;i < Sz;++i) {cout<< "HP =" <6.

#include <iostream>using namespace Std;/*class.cpp*/struct a{private:int i,j,k;public:int f (); void g ();}; int A::f () {return i + j + k;} void A::g () {i = j = k = 0;} Class b//However, the use of class in C + + has gradually become a non-essential keyword. It is the       same as every aspect of the struct//, except that the member in class is private by default, and the   //member in the struct defaults to Public{int i,j,k;public:int f (); void g ();}; int B::f () {return i + j + k;} void B::g () {i = j = k = 0;} Class x//Many people like to use a more struct-like style to create a class,       //Because you can overload the "default private" class behavior by beginning with public {public:void interface_function ();p rivate : void Private_function (); int internal_representation;}; int main () {return 0;}


7.

#include <iostream>using namespace std;/*stash.h*/#ifndef stash_h_#define stash_h_class stash{int size;             Size of each spaceint quantity;                 Number of storage spacesint next;   Next empty spaceunsigned char* storage; The storage pointer is a unsigned char*. This is the smallest memory chip supported by the C compiler, although it may be larger than the largest in some machines//, depending on the implementation. The memory that storage points to allocates void inflate (int increase) from the heap, and the/*inflate () function uses realloc () to get a larger block of space for stash. ReAlloc () assigns a stored-order head address that is already assigned and wants to be redistributed as its first parameter (if this parameter is zero, for example, Initialize () is just being called, realloc () allocates a new block). The second parameter is the new length of the block, and if the length is smaller than the original, the block will not need to be copied, simply tell the heap manager that the rest of the space is idle. If the length is larger than the original, there is not enough phase space in the heap, so allocate a new block and copy the memory. ASSERT () Check to make sure that the operation was successful. (If the heap is exhausted, malloc (), Calloc (), and realloc () all return zeros. ) */public:void Initialize (int Size),//initialize () completes the necessary setting for the struct stash, which is to set the internal variable to the appropriate value. Initially, the set//storage pointer is zero, and the size indicator is set to zero, indicating that the initial store is not allocated.           void Cleanup ();   Clear int Add (void* element); The Add () function inserts an element on the next available seat in the stash. First, it checks if there is free space, such as//fruit No, it is used afterThe inflate () function that is described in the polygon expands the storage space.   void* Fetch (int index);              Fetch () First look at whether the index is out of bounds, if not out of bounds, return the desired variable address, the address is computed using the same method as in//add () int count (); Returns the size of the stored space}; #endif


8.

#include <iostream>using namespace std;/*stack.h*/#ifndef stack_h_#define stack_h_class stack//This nested struct is called Link, which includes a pointer to the next link in the table and a pointer to the data stored in the link, if the next pointer is zero, which means the footer. {struct link{void* data;link* next;void Initialize (void* data, link* next);} *head;public:void Initialize (), void push (void* Data), void* Peek (), void* pop (), void Cleanup (),//cleanup remove each stack element, and release the data pointer}; #endif


9.

#include <iostream>using namespace std;/* reduce duplicate compilation handle.h handle class */#ifndef handle_h_#define Handle_h_class handle{ struct cheshire;//struct Cheshire; is a type description or class declaration that is not fully specified (the definition of a class contains the body of a class) cheshire* smile;public:void initialize (); void Cleanup (); int read (); void change (int);}; #endif

#include "handle.h" #include <stdlib.h> #include <assert.h>struct handle::cheshire//cheshire is a nested structure, So it must define the struct Handle::cheshire {//In handle::initialize (), allocate storage space for the Cheshire struct in Handle::cleanup () in the range separator to be disposed of in the space { int i;} void Handle::initialize () {smile = (cheshire*) malloc (sizeof (Cheshire)); assert (smile); smile->i = 0;} void Handle::cleanup () {free (smile);} int Handle::read () {return smile->i;} void Handle::change (int x) {smile->i = x;}

#include "handle.h"/* Client programmers only have access to the public interface part, so just modify the part in the implementation, these files will not have to recompile */int main () {handle u;u.initialize (); U.read ( ); U.change (1); U.cleanup (); return 0;}


Three. Exercises + answers

1) Create a class that has public, private, and protected data members and function members. Create a pair of this class to see what compile information will be obtained when trying to access all of the class members.

#include <iostream>using namespace Std;class people{string phonenumber;public:int age;string name;string sex; Protected:string address;}; int main () {people p;p.age = 19;p.name = "John";p. Sex = "man";//p.address = "Shanghai";     Protected error Cannot access//p.phonenumber = "123456789";p rivate error cannot access return 0;}


A.error C2248: ' Address ': cannot access protected member declared in class ' people '

B.error C2248: ' PhoneNumber ': Cannot access private member declared in class ' people '

2) Create a class and a global friend function to handle the private data of the class.

#include <iostream>using namespace std;struct a{int I;char c;float f;public:void Initialize (); void G (); friend void h ();}; void A::initialize () {i = 0;c = ' 0 '; f = 0.0;} void A::g () {cout<<i<< "" <<c<< "" <<F<<ENDL;} void H () {A a;a.i = 1;A.C = ' 1 '; a.f = 1.0;cout<<a.i<< "" <<a.c<< "" <<A.F<<ENDL;} int main () {A b;b.initialize (); B.G (); H (); return 0;}


3) Modify the HANDLE. Cheshire in CPP, recompile and concatenate this file, but do not recompile USEHANDL.CPP.

#include "handle.h" #include <stdlib.h> #include <assert.h>struct handle::cheshire//cheshire is a nested structure, So it must define the struct Handle::cheshire with the range separator {                       //in Handle::initialize (), allocate storage space for Cheshire struct in Handle::cleanup () In these spaces are released {int i;int* p;}; void Handle::initialize () {smile = (cheshire*) malloc (sizeof (Cheshire)); assert (smile); smile->i = 1;smile->p = NULL;} void Handle::cleanup () {free (smile);} int Handle::read () {return smile->i;} void Handle::change (int x) {smile->i = x;}


The above answer is for reference only, if have the mistake hope everybody to point out, thank everybody ~

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

"C + + Programming thought" third chapter hidden implementation (exercise + answer)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.