C from scratch (11) The above-related knowledge has introduced the concept of customized types of members variables and member functions, and give their respective semantics, this article continues to explain the content of the custom type And explain the respective semantics. The provision of the permission member function makes the semantics of the custom type from the resource to have a functional resource. What is the functional resources? For example, to map the radio into a number, the operation that needs to be mapped has the frequency of adjusting the radio to receive different stations; adjust the volume of the radio; turn the radio to prevent power loss. To this end, the radio should be mapped to the structure. Similar to: struct radiogram {double frequence; / * frequency * / void turnfreq (double value); // change frequency float volume; / * volume * / void Turnvolume (float value); / / Change the volume float power; / * Power * / void Turnonoff (Bool Bon); / / Switch Bool bpoweron; // Is Open}; The above Radiogram :: Volume and Radiogram :: Power Since the definition Members of Radiogram, so their semantics are a radio frequency, a radio volume and a radio of a radio. The semantics of the remaining three member functions are also the same as the frequency of a radio, change the volume of a radio and turn a radio. Pay attention to "a", which radio, is still not known. Only when a specific radio on the left will be known when the member operator combines one of them, this is why they are called offset. Types of. This will be explained in detail in the next article. Note Problem: Why is the three operations just mapped to a member function of structure Radiogram? Because the radio has such a function? So do you want to choose watermelon, cutting the scorpion and watermelon, do you want to define a structure, then define three elections, cut, and eat member functions? ? Isn't it very absurd? The three operations of the former are for the members variables of the structure, while the latter is for the structure itself. Then change into a snack, hamburger, eat fast food, eat snacks, fries, and drinking a snack. If the two eating and a drinking operation here becomes a fast food, it is a function of fast food? ! This is actually a question of programming, and here is actually the so-called object-oriented programming idea. Although it is a very good idea, it is not necessarily suitable, the next article will discuss in detail. Above we said that the retroactive station is functional, because we do not directly change the frequency of the radio directly, you must change the received frequency through the knob, the same, the same, the volume is also adjusted by adjusting the volume knob. Implemented, due to the power reduction caused by booting, it is not directly caused by indirectly by listening to the radio. Therefore, all members of Radiogram :: Power, Radiogram :: Frequency have a special feature - outside, this radio is unable to change their. To this end, C provides a syntax to implement this semantic. In the type definition, this format is given:
Here, the
Therefore, it is provided as a grammar, and the compiler is reviewed, allowing us to write a more semantic code that meets the world of our lives. Note that you can union abc {long a; private: short b;} ;. There is no modification here before the ABC: A, which is PUBLIC or protected? It is believed that the so many examples from the previous move have also been seen, it should be public, which is why I have always used Struct and Union to define a custom type, otherwise the previous example will be an error. The previous article is only a small difference between the structure and classes, that is, when the member does not make modifications, for the class, that member will be private instead of public, that is, the following will be wrong. Class ABC {Long a; Private: Short B;}; ABC A; A.A = 13; ABC:: A is considered to be a private. From this, it can be seen that the structure is used to map resources (resources that can be used directly), and class is used to map with functional resources. The following will discuss the differences in semantics in detail. The structure and destructive understand the things mentioned above, it will clearly have the following questions: struct abc {private: long A, b;}; abc A = {10, 20}; Is the initialization assignment variable A is correct? ? Of course, it is wrong, otherwise this is a vulnerability (the outside world can be modified). However, in some casements need to be initialized to ensure some logical relationships, and the concepts of constructors and sectors are proposed for this C , respectively correspond to initialization and sweeping operations. Before you understand this, let's take a look at what example (instance). An example is an abstract concept, indicating an objective existence, and the concept of "the world" that will introduce this concept is close. For example: "This is a table" and "this table", the "table" of the former is a kind, the latter "Table" is an example. There are 10 sheep here, saying that there are 10 sheep examples, while sheep is just a type. Examples can be simply considered to be objective objects, and humans have been divided into various objects for convenience. Therefore, it is not given an example of a TV set, and a TV set is given. An example of a TV set. Similarly, the code of the program is written, and only one instance of that program is running only when it is executed. If it does not perform it, it is required to execute it, for a multi-task operating system, you can call two instances of that program are being executed. If you open two Word files, there are two The example of the Word program is running. In C , only numbers can be operated, a number is an instance (which can be seen in the following description), more general, the address of the memory that identifies the record number is an instance, that is, the variable For an example, the corresponding type is the type of object that said above. For example: long a, * pa = & a, & ra = a;, two instances are generated, one is a LONG instance, one is an instance of long * (note that the instance is not generated, but RA is still Is an instance). Again, for a custom type, such as: Radiogram AB, C [3]; example, four Radiogram examples are generated.
For an instance of a custom type, the corresponding constructor will be called when it is generated; the corresponding destructor will be called. Who is called? The compiler is responsible for helping us write the necessary code to achieve the call of the corresponding constructor and destructure. The prototype of the constructor (ie the type corresponding to the function name, such as Float AB (Double, Char); the prototype of float (double, char) is: directly using the type name of the custom type as a function name, no return value Type, parameter is casual. For the destructor, the name is the front add symbol "~" of the corresponding type name, no return value type, must have no parameters. As follows: struct abc {abc (); ABC (long, long); ~ abc (); bool do (long); long a, count; float * pf;}; abc :: abc () {a = 1; count = 0; PF = 0;} ABC :: ABC (long Tem1, long Tem2) {a = tem1; count = tem2; pf = new float [count];} ABC :: ~ abc () {delete [] PF; } BOOL ABC :: DO (long cou) {float * p = new float [cou]; if (! p) returnaf false; delete [] pf; pf = p; count = cou;} extern abc g_ABC; Void main () {Abc A, & r = a; A.DO (10); {Abc B (10, 30);} ABC * P = New ABC [10]; delete [] p;} ABC G_A (10, 34), g_p = new abc [5]; the above structure ABC defines two constructor (note that two overload functions), the name is ABC :: ABC (actually converted by the compiler to a different symbol For connection purposes). A destructor is also defined (note only one, because it must be no parameters, it will not be overloaded), the name is ABC :: ~ abc. Look at the main function, first pass ABC A; define a variable because you have to assign a memory on the stack, that is, create a number (creating a digital memory, resulting in a number, because the memory can't be numb), In turn, an ABC instance is created, which in turn calls the constructor of the ABC. Since the parameters are not given here (later description), ABC :: ABC () is called, and A.a is 1, A.PF and A.count are 0. The variable r is then defined, but since it is ABC &, it is not allocated on the stack, thereby no creating an instance without calling ABC :: ABC. Then call A.DO, allocated a memory and put the first address in A.PF. Note the definition of the above variable B, which used the previously mentioned functional initialization mode. It calls the constructor ABC :: ABC (long, long) of ABC through the format called by the function, to initialize instance B of the ABC. Therefore, B.A is 10, b.count is 30, b.pf is the first address of a memory block. However, pay attention to this initialization mode and the "{}" mode previously mentioned, the former is initialized by a function call, while the latter is a compiler to initialize (by generating the necessary code).
Since the function is not called, the speed is slightly faster (the overhead of the function is described in "C from zero (fifteen)"). It should also be noted that ABC B = {1, 0, 0}; because the structure ABC has defined two constructor, it can only be initialized using a functional initialization, and cannot be initialized by "{}". The above B is in a pair of braces, recalls the scope of the previously emitted variable, so when the program is running to ABC * P = New ABC [10];, the variable B has disappeared (beyond its role), That is, the memory syntax assigned has been released (actually because it is not released), there is no release of the ABC, and the memory allocated in ABC :: ABC (long, long) Release out to achieve the sweep function. For memory allocated on the heap, since NEW ABC [10], 10 ABC instances will be created, which in turn calls every instance ABC :: ABC (), note that ABC :: ABC is unable to call Long, long), because the NEW operator assigns the memory space required by 10 instances at once, and C does not provide grammar (such as using "{}") to implement 10 instances of disposable assignments for initialization. The delete [] p;, this releases the rigid memory, which is destroyed 10 instances, so the destructor of the ABC is called 10 times to perform 10 sweeping operations. Note that the global variable g_abc is declared, because it is not defined, no memory, no instance is generated, so the constructor of the ABC is not adjusted, and G_A is a global variable, C guarantees the constructor of global variables to start execution Before the main function is called, the destructor of all global variables is called after the main function is executed (this is the compiler to implement, "C will be discussed further from Zero (19)". Therefore, the call to G_a.abc (10, 34) is before A.ABC (), even if its position is in a definition statement of A. The number of initialization of global variable g_p is calculated by the New operator. The result will allocate memory on the heap, and then generate 5 ABC instances to call ABC :: ABC () 5 times, since it is initialized G_P When assignment is performed, this 5 calls are also preceded before A.ABC (). Since G_P is just a record first address, but to release these 5 instances, you must call Delete (not necessarily, you can not call DELETE to release the memory returned by New, "C is noted from zero (19)"), but The above is not called, so until the end of the program will call the destructor of the five instances, what will be? The so-called memory leakage problem is discussed later. Therefore, it means that the number of memory has just been assigned, not initialized, then this memory is called raw data (Raw Data), and the number must be mapped in the algorithm, but there is a digital validity. For example, this number cannot be a negative number, because there is no meaning. So after the original data is obtained, you should first constructed the call to ensure the correct meaning of the corresponding instance.
The destructor represents the sweeping work, just like the above, during a period of operation (i.e., the period of operation of this instance is executed), then makes it properly released. Another example is of this example and other instances, depending on ensuring the release relationship (because this instance is about to be destroyed), if a node map is used by a node map, this node should be released in its destructor. Relationship with other nodes. Delivery and inheritance We define class radiogram to map radios, if you need to map digital radios, it is the same as the radio, that is, the radio has something, but there are more automatic search, storage stations, settles and delete tables. Function. A type system is proposed here, that is, if an instance is a digital radio, it must also be a radio, ie an example of a radio. For example, apples and pears are fruit, the examples of apples and pears must also be an example of fruit. Here are three types: fruit, apples and pears. Among them, the fruit is an apple's parent class (parent type), and Apple is a subclass of fruit (subtype). Similarly, fruit is also the parent class of pears, pears are subclasses of fruits. This type of system is very meaningful, because human beings use this way to cognition the world, it is very in line with human thinking habits, so C has put forward a special syntax to provide support for this semantic. When defining a custom type, then ":" after the type name, then pick up the PUBLIC or Protected or Private, then write the type name of the parent class, and finally the type definition "{}" and related writing, as follows: class DigitalRadiogram: public radiogram {protected: double m_Stations [10]; public: void SearchStation (); void SaveStation (unsigned long); void SelectStation (unsigned long); void EraseStation (unsigned long);}; for the above will be defined radiogram Digitalradiogram's parent class, Digitalradiogram defined as a subclass of Radiogram, called class Radiogram to derive class Digitalradiogram, class Digitalradiogram inherited the class Radiogram. 5 mapping elements have been generated above, that is, the above four member functions and 1 member variable, but actually. Since it is derived from Radiogram, seven mappings will be generated, which is 7 members of the class Radiogram, but the name changes, all become Digitalradiogram :: modification, not the original radiogram :: modification, but the type does not change. For example, the name of one of the map elements is Digitalradiogram :: m_bpoweron, the type BOOL RADIOGRAM ::, the mapping offset does not change, still 16. Also map elements Digitalradiogram :: Turnfreq, type Void (Radiogram ::) (double), the mapped address is still not changed, the address corresponding to Radiogram :: TurnFreq.
Thus it may be as follows: void DigitalRadiogram :: SaveStation (unsigned long index) {if (index> = 10) return; m_Station [index] = m_Frequency; m_bPowerOn = true;} DigitalRadiogram a; a.TurnFreq (10); a.SaveStation (3); Although there is no declaration Digitalradiogram :: Turnfreq, it can still call it because it is derived from Radiogram. Note Because A.TurnFreq (10); there is no writing full name, it is actually A.Digitalradiogram :: TurnFreq (10); because the number type on the left of the member operator is Digitalradiogram. If DIGITALRADIOGRAM is not derived from Radiogram, it will not generate 7 maps mentioned above, and the result is A.TurnFreq (10); will errors. Note that in the SaveStation, write m_frequency directly, it is equivalent to this-> m_frequency, because this is DigitalRadiogram * (because in DigitalRadiogram :: SaveStation), actually this-> DigitalRadiogram :: m_frequency, and therefore, If it is not derived from Radiogram, it will be an error above. And it matches the type, it is easy to know: void (Radiogram :: * P) (double) = Digitalradiogram :: TurnFreq; Although this is DigitalRadiogram :: Turnfreq, its type is Void (Radiogram ::) (Double). Note that M_BPoweron is used in SaveStation, which is defined into private members in Radiogram, that is, the subclass is not accessible, and saveStation is a member function of its subclasses, so it will be wrong, and the permissions are not enough. What is the respective permissions of 7 mappings generated by derived? First look at the derived code: Class Digitalradiogram: Public Radiogram {...}; Here, this is called Digitalradiogram from Radiogram, which is called protection inheritance if it is changed to protected. What's the difference? Map elements generated by public inheritance (7 mapping elements generated from Radiogram derived), their respective permissions attributes do not change, the above Digitalradiogram :: m_frequency is still protected by class Digitalradiogram, while Digitalradiogram :: M_BPoweron It is still private. Protecting inherits All public members become protected members, others constant. That is, if the protection inherits, Digitalradiogram :: TurnFreq will be protected for Digitalradiogram. Private inheritance will turn all parent members into a Private for subclasses. Therefore, if private inherits, Digitalradiogram :: TurnFreq is Private for Digitalradiogram.
It can be seen so simple, that is, no matter what inherits, it specifies a permission, and the mapping element that is higher than this permission is to reduce the permissions (note is the subclass). , Then inherit to the subclass. It has always emphasized that "for subclasses", what do you mean? As follows: struct a {long a; protected: long b; private: long c;}; struct b: protected a {void ab ();}; struct c: private b {void abc ();}; void b :: Ab () {b = 10; c = 10;} VOID C :: ABC () = 10; b = 10; C = 10; ab ();} a a; b; c c; aa = 10 BA = 10; B.Ab (); C.Ab (); The definition of B above is equivalent to Struct B {Protace: Long A, B; Private: long C; public: void ab ();} ;. The definition of C is equivalent to Struct C {Private: Long A, B, C; Void ab (); public: void abc ();}; therefore, b :: abc () b = 10; no problem, but C = 10; There is a problem, because the compiler shows that B :: C is generated from the parent class, and it is a private member for the parent class, so the subclasses are free to access, errors. Then look at C :: ABC, A = 10; and b = 10; there is no problem, because they are protecting members for B, but c = 10; will errors, because C :: C is for parent class B It is a private member, no permissions, failed. Then AB (); because C :: AB is a public member for parent class B, there is no problem. Then there is aa = 10; no problem; ba = 10;, errors, because B :: A is the protection member of B. B.Ab (); no problem; c.ab ();, mistake, because C: : AB is a private member of C. It should be noted that PUBLIC, Protected and Private are not type modifiers, just provide some information on grammar, and the type of member who has received does not change, regardless of its protection inheritance or public inheritance, the right place is There is no relationship with the type of place to use members. What is the place to use members? As follows: long (a :: * p) = & a :: a; p = & a :: b; void (b :: * pb) () = b :: ab; void () = C :: ABC; PC = C :: ab; there is no problem with the initialization operation of the variable P, which is used here. But at P = & A :: B;, due to the use of A :: B, the compiler is to check the place where the code is located, and it is found that it belongs to the outside, so the error is not enough. The same is not a problem with the value of PB, but PC = C :: ab; it is wrong. For B.a = 10;, due to the member operator, the member B: A of the class B is used, so the permission check is permissible, and the permissions are not enough to report an error.