How to rewrite C++ code into C language code in embedded system

Because the C++ interpreter takes up about 500k more storage space than the C language interpreter. In order to save limited storage space, reduce costs, and improve efficiency, it is necessary to rewrite the source program written in C++ language into C language.

The biggest difference between C++ and C is the concept and characteristics of classes in C++. The problem of changing C++ to C is transformed into the problem of how to convert classes into classes.

There are two methods:

The first is to remove the object-oriented features in C++, first fully understand the logic of the source code, and then rewrite it; the second is to retain some of the object-oriented features in C and use structures to implement class functions.

The first method is okay when the number of classes is small. If the number of classes is relatively large, understanding all the source code and then rewriting it will be very time-consuming and error-prone. What’s more, if you encounter a large It is almost impossible for a project to fully understand the source code.

If there are more than 140 classes in the program, you need to use the second method at this time. You can change each class one by one without too much difficulty. If it is not a typo, there will be almost no mistakes, and there is no need to understand it at all. Program logic, maybe after changing it, you still don’t know anything about the functions that the program wants to achieve. This is not to say that knowing nothing is good for everyone, but I just want to say that this method has nothing to do with the program logic itself.

The following is a preliminary discussion on some features of C++ and how to implement or replace them in C.

Description:

  • Function Ixx is the implementation of the constructor of class xx

  • The member functions of the original class are changed to functions whose prefix is the structure name + _’

  • The function pointer U is the declaration of the destructor of the original class

  • U+ structure name is the implementation of the destructor of the original class

  • Fun-_ + The structure name points to the member function pointer of the structure

  • We will not explain it again if we encounter the above situation in the future.

Member functions and data members of the class

Since struct does not control the access rights of members, additional mechanisms must be added for access control, which complicates the program, so the control of access rights can only be given up.

1)The data members of the class can be directly converted into the data members of the structure in C.

2) Functions need to be converted into corresponding function pointers, because function declarations and definitions are not allowed in structs. If there are modifiers such as virtual and inline before the function, they should also be removed. For example, the function void funca (int a); should be changed to void (*funca) (struct B *p, int a); you can see that in the prototype of the function pointer, add A pointer to struct B is obtained. This is because to operate the members of the class within the function, the pointer must be used to specify the members of the structure. In the member function of the class, there is actually an implicit this pointer pointing to itself in the parameter column.

3) For static members, they must be defined as global variables or global functions, because there cannot be static members in the structure.

Constructor of class

When a class is instantiated, the default constructor of the class will be called. In the struct, a function pointer with the same name must be defined to point to an initialization function with a constructor function. Different from the constructor, a function must be added to the initialization function. Pointer initialization statement. When using it, use malloc instead of new when creating structure variables, and call the initialization function manually at this time.

As shown in the following example:

class A</code><code>{<!-- --></code><code>public:</code><code> A();</code><code> ~A( );</code><code> void func(int a);</code><code> private:</code><code> int b;</code><code>};

</code><code>A::A()</code><code>{<!-- --></code><code> b=0;</code><code>}</pre >
<p></p>
<p><code>void A::func(int a)</code><code>{<!-- --></code><code> b=a;</code><code>}</code></p>
<p></p>
<p><code>typedef struct classA A;</code><code>struct classA</code><code>{<!-- --></code><code> void (*A)(struct classA *p) ;//Constructor pointer</code><code> void (*U)(struct classA *p);//Destructor pointer</code><code> void (*func)(struct classA *p,int a);</code><code> int b;</code><code>};</code></p>
<p></p>
<p><code>void fun_A(A *p)</code><code>{<!-- --></code><code> p->func=classA_func; //Initialize the function pointer</code><code>}</code></p>
<p></p>
<p><code>void IA(A *p) //Constructor, the naming rule is to add I before the class name</code><code>{<!-- --></code><code> fun_A(p);</code><code> p->b=0; //Part of the original constructor</code><code>}</code></p>
<p></p>
<p><code>void classA_func(A *p,int a)</code><code>{<!-- --></code><code> p->b=a;</code><code>} </code></p>
<p></p>
<p>Where used, use the following method:</p>
<p></p>
<pre> A *s=(A*)malloc(sizeof(A));</code><code> s->A=IA;</code><code> s->A(s);</code> pre>
<p></p>
<p><strong>Destructor of class</strong></p>
<p>The job of a class's destructor is to release the resources it occupies.</p>
<p>In C, no matter which struct it is, the function pointer U is used instead of the destructor. The reason why all structs use pointers U is based on the following situations:</p>
<p>If the subclass pointer is assigned to the base class pointer, the base class pointer does not need to consider which function name's destructor is called when it is released, and only needs to call the member function U. Member function U needs to be specified in the fun_classname() function like a general member function.</p>
<p>The destructor of a class is called by the system, but in C it must be called explicitly. As for when to call, you must judge accurately.</p>
<p></p>
<p><strong>Copy constructor of class</strong></p>
<p>The main purpose of the copy constructor of a class is to speed up the construction of classes in the following situations:</p>
<p><strong>1. </strong> Pass it to the function as a parameter. (additem(Itema))</p>
<p><strong>2. </strong>As a function return value.</p>
<p><strong>3. </strong>As parameters when instantiating a class.</p>
<p>In these three cases, the system directly calls the copy constructor of the class instead of the constructor.</p>
<p><strong>Note: C=D; will not call the copy constructor. In this case, the method of overloading the =’ operator is used. (See operator overloading for details)</strong></p>
<p>Since when defining struct variables in C, all pointers are used and the copy constructor is not used, so it is not considered for the time being. For original function parameters or return values that require class variables, all must be converted into class pointers. The situation of using parameters when instantiating a class can be solved by defining an additional constructor with parameters.</p>
<p></p>
<p><strong>Inline functions and virtual functions of classes</strong></p>
<p>All modifiers inline and virtual of inline functions and virtual functions must be removed. The inline function body should be removed, and the inline function should be defined as a function outside. as follows:</p>
<ul><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul>
<pre>class B</code><code>{<!-- --></code><code> ...</code><code> virtual void funb();</code><code> inline int add() const {return a + b;};</code><code> private:</code><code> int a;</code><code> int b;</code><code> ...</code><code>}

Change to:

typedef classB B;</code><code>struct classB</code><code>{<!-- --></code><code> …</code><code> void (*funb )(struct classB *p);</code><code> int (*add)(struct classB *p);</code><code> int a;</code><code> int b;</code><code>}

void classB_funb(B *p){}

int classB_add(B *p){ return p->a + p->b; }

void fun_classB(B *p){ p->funb=classB_funb; p->add= classB_add;}

Reload

There are two types of overloading in classes: function overloading and operator overloading:

1) Overloading of functions

The conditions that function overloading meets are: the function name is the same, but the number of parameters or parameter types are different.

In this way, when calling, different functions will be called based on the parameters you enter.

In C, we have to give them different names, and there is no other solution.

2) Operator overloading

Operator overloading is just to satisfy general operator usage habits without causing errors.

Operator overloading is not supported in C. You can define a function to implement this function.

This is a general class modification.

7. Class inheritance

1) Single inheritance
If there is an inheritance relationship between classes, first modify the base class according to the general class modification method, and then copy all the definitions of the base class to the front of the subclass.

Except for changing the base class constructor name to the subclass constructor name, no other changes can be made to the base class definition. And call the constructor of the base class in the constructor, and then if the subclass overrides the function of the base class, the function pointer must be redirected to the subclass function. This is to maintain the dynamic binding features brought by class inheritance.

The inheritance relationship between classes is complex and changeable. In order to ensure that the base class is unique among all subclasses and can be easily modified, the best way is to make the structure part of the base class into a macro and use it directly in the subclasses. That’s it.

2) Multiple inheritance
I personally think that it is best not to use multiple inheritance. It will bring some problems and there will be problems with multiple inheritance paths. Unless it is used for programming convenience, such as inheriting interfaces, etc.
Multiple inheritance can also be changed. Copy all members of multiple base classes to subclasses. If you encounter duplicate member names, add a prefix in front to distinguish them. Of course, this refers to the same between the base classes. If there are duplicate names between the derived class and the base class, the base class will be overwritten.

Other

The above are the main features and modification methods in C++ that are the most different from C and the most commonly used.

There are others such as the use of templates, etc. These are all for the convenience of programming and code reuse. There is no such function in C language, so I have to write multiple functions to implement them separately.

In addition, the & amp; symbols in the parameter list should be replaced with pointers, and the default value should also be removed. When calling, be careful to write the default value.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. C Skill Tree Home Page Overview 194357 people are learning the system