Encapsulation-an interesting C ++ example

Source: Internet
Author: User

An interesting phenomenon, excerpted from the original article "C ++ from scratch (12)-What is object-oriented programming ideology" on the cloud blog of csdn: http://blog.csdn.net/chuiyun/archive/2004/11/26/194722.aspx.

The reason why this article is excerpted is that I am surprised that the following example can be compiled and used to directly access private variables by modifying the private value of the class to public in the referenced file, and can be accessed and assigned values normally.
Below is the original excerpt. If you are interested, try to compile a code experiment.

-------------------------------------------------------------------

Encapsulation

First, let's take a look at the design of the following classes that can often be seen in the explanations of objects in various VC tutorials.
Class person
{PRIVATE: Char m_name [20]; unsigned long m_age; bool m_sex;
Public: const char * getname () const; void setname (const char *);
Unsigned long getage () const; void setage (unsigned long );
Bool getsex () const; void setsex (bool );
};
The above defines all member variables as private, and then provides three pairs of get/set functions to access the above three member variables (because they are private and cannot be directly accessed by the outside world ), these three pairs of functions are all public. Why? These textbooks encapsulate the internal memory layout of class persons, in this way, the outside world does not know how it is deployed in the memory and thus can ensure the effectiveness of the memory (only the class itself operates its instance ).
First of all, we need to confirm the absurd design above. It makes no sense to be authentic and "Unlocked. Then let's look at the so-called memory layout encapsulation. Recall why the header file must be included at the beginning of each source file to be used in C ++ from scratch (10. Assume that the above statement is in person. h, and then use the class person in B. cpp, which would have to be # include "person. H". replace it with the following:
Class person
{Public: Char m_name [20]; unsigned long m_age; bool m_sex;
Public: const char * getname () const; void setname (const char *);
Unsigned long getage () const; void setage (unsigned long );
Bool getsex () const; void setsex (bool );
};
Then use the class person in B. cpp as usual, as shown below:
Person A, B; A. m_age = 20; B. getsex ();
Here, the person: m_age is used directly. Even if you do not do such a bad action, # include "person. H" is still used, as follows:
Struct person {char m_name [20]; unsigned long m_age; bool m_sex ;};
Person A, B; person * PP = (person *) & A; PP-> m_age = 40;
The member person: m_age of instance a whose person is still directly modified above. How can I hide the memory layout ?! Recall the role of the Declaration. The memory layout of the class is required when the compiler generates an object. It cannot hide anything about the object implementation for any code that uses the object, otherwise, the compiler cannot compile the corresponding code.
In terms of semantics. The person ing is not the concept of a person in the real world. It should be the record buffer in the table that stores information about a person in a database, so should the buffer have the functions represented by those three pairs of get/set? The buffer zone is used to buffer data. It is used by other operations After buffering, just like a box. Therefore, the above three pairs of get/set do not have to exist, and the three member variables cannot be private. Of course, if the person ing is not a buffer, and there are semantics as described above in other worlds, there is no problem with the definition as above, however, it would be a big mistake to define classes because of the encapsulation of the memory layout.
The error above is that it does not understand encapsulation. To illustrate the encapsulation, let's take a look at the MFC (Microsoft Foundation Class Library -- Microsoft function class library), a library file that defines many classes, most of which are encapsulation design. The definition of cfile class in library files described in SDK description. It can be seen from the name that it maps to the file concept in the operating system, but it has such a member function-cfile: open, cfile: Close, cfile :: read, cfile: write. What's the problem? These four member functions map object operations rather than file functions, including opening a file, closing the file, reading data from the file, and writing data to the file. Isn't this the same as the semantics of the previously mentioned member functions? The preceding four operations share a common nature. They are all operations applied to the file resource. They can be called "functions". For example, a file has the "opened" function, it has the "read" function, but note that they are not actually a file function.
According to the original statement, the file should be mapped into a structure, such as file. Then, the four operations above should be mapped into four functions, and the functions of namespace should be reused, as follows:
Namespace ofile
{
Bool open (file &,... ); Bool close (file &,... );
Bool read (file &,... ); Bool write (file &,... );
}
The above namespace ofile indicates that all the four functions are file operations, but each of the four functions has a file & parameter. Recall that non-static member functions all have a hidden parameter this, so an amazing idea came into being.
Think of all the sets of operations on a certain resource as a resource and map it into a class. The object of this class is the operation on an object. This method is called encapsulation, the class is called a packaging class or an encapsulation class. Obviously, the packaging class maps "operations on a certain resource" and is an abstract concept, that is, the packaging class objects are all stateless objects (it should be a stateless object logically, however, if there is a link between multiple operations, there may still be states, but its semantics also changes accordingly. For example, if you have another cfile: flush member function that is used to refresh the buffer content, there will be at least one status-buffer, and you can also have a status record that has already called cfile: write, if not, you do not need to refresh it ).
Now we should be able to understand the meaning of encapsulation. Encapsulates operations on a certain resource into a class. This packaging class maps not to a "noun concept" defined in the world ", it is an abstract concept defined by the "verb concept" or "operation on a certain concept" in the world. Since a packaging class encapsulates operations on a certain resource, the packaging class object must have an attribute to indicate the object to be operated. For cfile in MFC, cfile :: m_hfile member variable (handle type), which is read in the main operation process of the packaging Class Object (cfile: Read and cfile: Write.
What are the benefits? Encapsulation provides a means to convert part of the "verb concept" in the world into objects, makes the program architecture simpler (multiple "verb concepts" are changed into a "noun concept", reducing the number of "verb concepts ), more object-oriented programming ideas.
However, the packaging objects and encapsulated objects should be differentiated. The packaging object is only a shell, and the encapsulated object must be a stateful object, because the operation is to change the state of the resource. For cfile, The cfile instance is a packaging object, which maintains a pair of encapsulated objects-file kernel objects (resources defined in Windows operating systems, represented by handle instances) -- reference in cfile: m_hfile. Therefore, the packaging objects are independent of the encapsulated objects. Cfile A; in this case, the value of A. m_hfile is 0 or-1, indicating that the referenced object is invalid. Therefore, if a. Read (... ); Will fail, because the resources applied by the operation are invalid. In this case, you should first call A. Open (... ) To bind a to a specific file kernel object, and call a. Close (... ); Will be unbound. Note cfile: After the close call, only the binding is unbound. This does not mean that a has been destroyed, because a maps not a file kernel object, but a packaging object for file Kernel Object operations.
If you think about it, you will find that Tigers can eat rabbits and rabbits can be eaten, so here it should be that the tiger has a function to "eat rabbits" or multiple rabbit packaging classes to encapsulate the "eat rabbits" operation? In fact, there is no problem. "Tigers eat rabbits" and "rabbits are eaten" are totally different operations. The former involves two types of resources, and the latter only involves one type of resources, therefore, the two can be implemented at the same time, depending on their semantics in the corresponding world. For the real world, it can be simply said that tigers have a "eat" function and can eat "meat", while animals inherit from "meat" and "autonomous initiative" in multiple ways, rabbits inherit from animals. Here, there is a class called "autonomous initiative", which means that an animal is conscious and can act on its own. In C ++, it is represented by a class with a member function, indicating that a function can be operated, however, the Radio also has functions such as adjusting the station. Is it hard to say that the radio can also be operated by itself ?! This is the significance of the world-operation.

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.