Object-Oriented Programming in C Language
The object-oriented language is closer to the human way of thinking, which greatly reduces the complexity of the code and improves the readability and maintainability of the Code, the traditional C code can also design beautiful code that is easier to read, easier to maintain, and less complex.
This article uses a practical example to illustrate this point.
Basic Knowledge Structure
In addition to providing basic data types, the C language also provides users with the ability to customize data types, that is, struct. In the C language, you can use struct to represent any entity. Struct is the prototype of classes in object-oriented languages. For example:
Typedef struct {
Float x;
Float y;
} Point;
Defines a point in a plane coordinate system. A point has two fields, x coordinate and y coordinate.
The fields in the struct are called struct members. The data type of the domain in the struct can be a simple data type, or other struct, or even the struct itself canNesting, Nesting makes it possible to do more and more imaginative. For example, a standard linked list structure can be defined as follows:
Typedef struct node {
Void * data; // data Pointer
Int dataLength; // Data Length
Struct node * next; // point to the next node
} Node;
We can see that the next pointer type in the struct node is also the node type. Data types can be customized. Struct behavior is expressed by function pointers. A function pointer is a pointer to a struct that provides an object-oriented mind, so that the struct has behavioral characteristics.
Pointer
Pointers are the soul of the C language. They are more flexible and powerful than other languages. Therefore, to learn the C language, you must have a good grasp of the pointer. The function pointer refers to the pointer to the first address of the function in the memory ing. Through the function pointer, you can pass the function as a parameter to another function and call it when appropriate, to Implement Asynchronous Communication and other functions.
For example, the signal registration function in UNIX/Linux is prototype as follows:
Void (* signal (int signo, void (* func) (int)
When using it, you need to define a signal processing function (signal handler) externally, and then use signal (sigNo, handler) to register the processing program on the process. When the signal occurs, the process can call back the signal processing function.
The prototype of this function is understood as follows:
#include
void (*signal(int signo,void(*func)(int)))(int);
Understanding of this complex function.
1. Use typedef for disassembly
typedef void(*sighandler_t)(int);sighandler_t signal(int signum,sighandler_t handler);
2. Understanding using function pointers
Int (* p )();
Obviously, the p Pointer Points to a function without any parameters and returns an int value;
Int (* fun ())();
The difference between this formula and the above formula lies in the replacement of p with fun (), that is, the return value of fun () is a function pointer. This function pointer (which can be considered as p) points to a parameter without any input, and the return value is int. Therefore,
void (*signal(int signo,void(*func)(int)))(int);
It can be regarded as the signal () function. This function has two parameters: an integer and a function pointer. The return value of this signal () function is also a function pointer, which points to a function with an integer parameter and the return value is void.
This function is too complex and meaningless. It is usually a simple signal processing function after typedef.
But what is the purpose of returning a function pointer? The signal function returns a function pointer to the previous signal processing program.
Use the function pointer as a member of the struct.
As mentioned above, a struct member can be a simple data structure or another struct, or a pointer. When the function pointer is used as a member of the struct, and these functions are only used to manipulate data in the struct, an independent entity can be formed, which contains both data, there are also operations on data, which naturally lead to the concept of class.
Features of object-oriented language
In general, inheritance, encapsulation, and polymorphism are considered to be three features that must be supported by object-oriented languages. It is precisely through these three features that they can reflect the advantages of forward object over process-oriented. Because of the publicity of language developers or other reasons, the object-oriented thinking on the surface needs to be implemented through the language as the carrier. However, in fact, object-oriented is a software design idea, it is completely unrelated to the specific implementation.
Even so, it is undeniable that these so-called pure object-oriented languages are much better than process-oriented languages in terms of code readability and matching with human natural thinking.
Object-oriented language support at the language level
We generally want to describe an object. Generally, we need to describe some attributes of this object. For example, a box is an object with six faces, with colors and weights, whether the attribute is empty or not, and can be put in and retrieved. In an object-oriented language, such an object is usually abstracted into a class ):
class Box{ clolr color; int weight; boolean empty; put(something); something get(); }
You can perform the following operations on the box:
Box. put (cake); Box. get (); // get something from the Box.
In a process-oriented language, objects are usually transmitted to a global function. In the same case, Box is often operated like this:
Put (Box, cake); // Put a cake into the Box Get (Box); // Get something from the Box
Obviously, the first form of code is more common sense. Therefore, most object-oriented languages provide detailed support at the language level, greatly increasing the readability and comprehensibility of the Code. C language, as a flexible and simple language, we can use the simple mechanism provided by C to implement such a beautiful code form.
C language object-oriented
As mentioned above, object-oriented is a software design concept and is language independent. In this section, I will give a list example to illustrate how to design object-oriented code in C language.
Interface Definition
An interface is an important concept in object-oriented language. An interface only promises to external entities what functions the interface can accomplish, but does not expose the implementation method. The advantage is that the implementer can adjust the implementation without touching the code of the interface user.
Let's take a look at the Interface Definition of the linked list.:
# Ifndef LIST_H_INCLUDED # define LIST_H_INCLUDED/*** @ author PENGRONG * @ date required */# ifdef _ cplusplusextern "C" {# endif/_ cplusplus/define data domain typedef struct data {int year; char * name;} Data; // define the node Structure typedef struct node {void * data; struct Node * next;} node; // statement of the linked list structure, typedef struct List {struct List * _ this; Node * head; int sizeOfList; void (* insertOfElement) (void * node, struct List * list ); // function pointer void (* drop) (void * node, struct List * list); void (* clearList) (struct List ** list); int (* getSize) (struct List * list); void * (* get) (int index, struct List * list); void (* print) (struct List * list);} List; // construct an empty linked List extern List * ListConstruction (); # ifdef _ cplusplus} # endif/_ cplusplus # endif/LIST_H_INCLUDED
In the List interface, you can clearly see that for a list object (that is, an object), you can perform insertOfElement, drop, clearList, getSize, get (index) on it) and print operations.
Interface implementation
1. Empty linked list Construction
/*** @ Author pengrong * @ date * @ function initialize a linked List */List * ListConstruction () {// Node of the linked List * node = NULL; // List * list = NULL; list = (List *) malloc (sizeof (List); node = (Node *) malloc (sizeof (Node )); list-> head = node; node-> data = NULL; node-> next = NULL; list-> insertOfElement = insertOfElement; // register the insert function on the list Object list-> drop = drop; list-> clearList = clearList; list-> sizeOfList = 0; list-> getSize = getSize; list-> get = get; list-> print = print; list-> _ this = list; // use the _ this pointer to save the list itself printf ("construction successful \ n"); return (List *) list ;}
2. Insert a data entry into the linked list
/*** @ Author pengrong * @ date 2016/01/19 * Insert an element in front of the linked List */void insertOfElement (void * data, list * List) {if (data = NULL | list = NULL) return; Node * current = (Node *) malloc (sizeof (Node )); // fill data current-> Data = (data *) data; current-> next = list-> _ this-> head-> next; list-> _ this-> head-> next = current; (list-> _ this-> sizeOfList) ++; printf ("insert sucessful \ n ");}
3. delete an element from the linked list
/*** @ Author pengrong * @ date 2016/01/19 * delete a node */void drop (void * data, List * list) {if (data = NULL | list = NULL) {printf ("data empty or list empty"); return ;} // head Node * t = list-> _ this-> head; // traverse Node * n = NULL; // delete Data * d1 = (Data *) data; int I = 0; for (I = 0; I
_ This-> sizeOfList; I ++) {// traverses the node pointer. The next node of the header node is the first node n = list-> _ this-> head-> next; if (d1-> year = (Data *) n-> data)-> year) & (strcmp (d1-> name, (Data *) n-> data)-> name) = 0) {// if the content is the same as list-> _ this-> head-> next = n-> next; free (n); free (d1); (list-> _ this-> sizeOfList) --; printf ("drop successful \ n"); break ;} else {list-> _ this-> head = list-> _ this-> head-> next; }}if (I >=list-> _ this-> sizeOfList) {printf ("drop failure \ n");} list-> _ this-> head = t ;}
4. Clear all elements in the linked list
/*** @ Author pengrong * @ date 2016/01/19 * @ param list * @ return void * @ function deletes all element nodes in the list. * The processing logic is that the linked list has a head member who only wants the first element of the linked list, * if its next attribute is NULL, the linked List is empty */void clearList (list ** plist) {if (* plist = NULL) {printf ("List empty "); return;} List * list = * plist; // point to the Node of the element to be deleted. Node * n = NULL; for (; list-> _ this-> head-> next! = NULL;) {// retrieve and delete node n. The next node to the header node is the first node n = list-> _ this-> head-> next; // point the pointer to the next element list-> _ this-> head-> next = list-> _ this-> head-> next; // delete node n // Delete the data Node space first, and then delete the Node space free (n-> data); free (n); (list-> _ this-> sizeOfList) --;} // Delete the header node // free (list-> _ this-> head); // Delete the linked list structure // free (list ); // * plist = NULL ;}
5. Get the chain table length
/*** @ Author pengrong * @ date 2016/01/19 * // obtain the length of the linked List element */int getSize (list * list) {if (List = NULL) {printf ("list empty"); return;} return list-> sizeOfList ;}
6. Obtain the elements at the index
/*** @ Author pengrong * @ date 2016/01/19 * // obtain the length of the linked List element */void * get (int index, list * List) {if (index <0 | list = NULL) {printf ("list empty or index <0;"); return NULL;} Data * indexData = NULL; // t is the Node * t = list-> _ this-> head-> next; int I = 0; for (I = 0; I
_ This-> sizeOfList; I ++) {if (I = index) {indexData = (Data *) t-> data; break ;} t = t-> next;} if (I >= list-> _ this-> sizeOfList) {printf ("yue jie") ;}return indexData ;}
7. All elements in a recurring table
/*** @ Author pengrong * @ date 2016/01/19 * // before printing, make sure that the linked list Pointer Points to a specific linked list memory block. * // Otherwise, the execution of this function program will crash. */Void print (List * list) {if (list = NULL) {printf ("list empty"); return;} int I = 0; node * tem = list-> _ this-> head; Data * data = NULL; for (I = 0; I
SizeOfList; I ++) {data = (Data *) list-> _ this-> head-> next-> data; printf ("name = % s, \ tyear = % d \ n ", data-> name, data-> year ); list-> _ this-> head = list-> _ this-> head-> next;} list-> _ this-> head = tem ;}
Test code
Int main (int argc, char ** argv) {List * plist; Data d1; plist = ListConstruction (); // apply for a Data storage space * pxiao = malloc (sizeof (Data); pxiao-> name = "xiaoming"; pxiao-> year = 19; plist-> insertOfElement (pxiao, plist); // Insert the second Data pxiao = malloc (sizeof (Data); pxiao-> name = "xiaoling "; pxiao-> year = 29; plist-> insertOfElement (pxiao, plist); // Insert the third Data pxiao = malloc (sizeof (Data )); pxiao-> name = "JBV"; pxiao-> year = 69; plist-> I NsertOfElement (pxiao, plist); // Insert the fourth Data pxiao = malloc (sizeof (Data); pxiao-> name = "XXX"; pxiao-> year = 89; plist-> insertOfElement (pxiao, plist); // output printf ("getSize \ t % d \ n", plist-> getSize (plist )); printf ("delete previous \ n"); plist-> print (plist); // delete a data d1.name = "xiaoling"; d1.year = 29; printf ("delete after \ n"); plist-> drop (& d1, plist); plist-> print (plist ); // obtain an element printf ("get a element \ n"); pxiao = plist -> Get (2, plist); if (pxiao! = NULL) {printf ("name = % s, \ tyear = % d \ n", pxiao-> name, pxiao-> year );} else {printf ("element no exist \ n");} // Delete the linked list plist-> clearList (& plist); printf ("clear hou \ n "); if (plist! = NULL) {plist-> print (plist); printf ("% d", plist-> getSize (plist ));} else {printf ("lian biao kong");} return 0 ;}
The running result is as follows:
: