C++解释器比C言语解释器占用的存储空间要大,想要在某些特定场所兼容C++代码,同时为了俭省有限的存储空间,降低本钱,也为了进步效率,将用C++言语写的源程序用C言语改写是很有必要的。
C++与C区别最大的就是C++中的类的概念和特性,将C++改为C的问题,就转换成如何将类化去的问题。
办法有两种:
将C++中的面向对象特征去掉,先全部了解源代码的逻辑,然后改写; 是在C中保存面向对象的局部特征,用构造体完成类的功用。
第一种办法,关于类的数目很少的状况还能够,假如类的数目比拟多,全部了解源代码,然后重写就很耗时间,而且很容易出错,更甚者,假如遇到大的项目想全部了解源代码简直是不可能的。
下面对C++的一些特性,以及如何在c里完成或者替代,作一些初步的讨论。
阐明:
函数Ixx为类xx的结构函数的完成。 原类的成员函数改为前缀为构造体名+‘_'的函数。 函数指针U为原类的析构函数的声明; U+构造体称号为原类的析构函数的完成; Fun-_+构造体名为对该构造体成员函数指针停止指向;
以后遇到上述状况将不再阐明。
一、类的成员函数和数据成员
由于struct没有对成员的访问权限停止控制,必需参加额外的机制停止访问控制,这样一来就使得程序复杂化了,所以只能放弃访问权限的控制。
关于类的数据成员能够直接转为C中构造体的数据成员。 函数则需转化为对应的函数指针,由于struct里不允许呈现函数的声明和定义。而函数前假如有virture,inline等修饰符也要去掉,如函数voidfunca(inta);改为void(*funca)(structB*p,inta);大家能够看到函数指针的原型里加了一个指针structB的指针,这是由于要在函数内部对类的成员停止操作,要靠该指针指定构造体的成员。在类的成员函数里,实践上在参数列里也隐含有一个指向本身的this指针。 关于静态成员则要定义成全局变量或全局函数,由于构造体中不能有静态成员。
二、类的结构函数
类在实例化的时分会调用类的缺省结构函数,在struct里,要定义一个同名函数指针指向一个具有结构函数功用的初始化函数,与结构函数不同的是,要在初始化函数里参加停止函数指针初始化的语句.运用的时分在创立构造体变量的时分要用malloc而不是new,并且这个时分要手工调用初始化函数。
如下例所示:
classA { public: A(); ~A(); voidfunc(inta); private: intb; }; A::A() { b=0; } voidA::func(inta) { b=a; } typedefstructclassAA; structclassA { void(*A)(structclassA*p);//结构函数指针 void(*U)(structclassA*p);//析构函数指针 void(*func)(structclassA*p,inta); intb; }; voidfun_A(A*p){ p->func=classA_func;//将函数指针初始化 } voidIA(A*p)//结构函数,命名规则在类名前加I{ fun_A(p); p->b=0;//原结构函数所作局部 } voidclassA_func(A*p,inta){ p->b=a; }
在运用的中央采用如下方式:
A*s=(A*)malloc(sizeof(A)); s->A=IA; s->A(s);
三、类的析构函数
类的析构函数所作的工作是释放所占的资源。
在C中,无论是哪个struct都用函数指针U替代析构函数。之所以一切的struct都用指针U是基于如下状况:
假如将子类指针赋给基类指针,基类指针在释放的时分不用思索调用哪个函数名的析构函数,只需调用成员函数U即可。成员函数U需求像普通成员函数一样在fun_类名()函数中指定。
类的析构函数是由系统调用的,在C中则要显式调用。至于何时调用,要精确判别。
四、类的拷贝结构函数
类的拷贝结构函数主要用处是加快以下状况下类的构建速度:
作为参数传给函数。(additem(Itema)) 作为函数返回值。 实例化类时作参数。
这三种状况下都是由系统直接调用类的拷贝结构函数而不是结构函数。
留意:C=D;不会调用拷贝结构函数,这种状况下运用的是重载‘='运算符的办法。(详见运算符重载);
由于C中定义struct变量的时分,运用的全部是指针,不会用到拷贝结构函数,所以暂不思索。关于原来函数参数或者返回值需求类变量的,要全部转化为类指针的方式。实例化类时作参数的状况,能够经过另外定义一个带参数的结构函数来处理。
五、类的内联函数和虚函数
内联函数和虚函数的修饰符inline、virture要全部去掉。内联函数体则要去掉,将内联函数在外面定义成一个函数。如:
classB { … virturevoidfunb(); inlineintadd()const{returna+b;}; private: inta; intb; … }
改为:
typedefclassBB; structclassB { … void(*funb)(structclassB*p); int(*add)(structclassB*p); inta; intb; } voidclassB_funb(B*p){ … } intclassB_add(B*p){ returnp->a+p->b; } voidfun_classB(B*p){ … p->funb=classB_funb; p->add=classB_add; }
六、重载
类中重载有函数重载和运算符重载两种:
1)函数的重载
函数重载满足的条件是:函数名相同,参数个数或者参数类型不同。
这样在调用的时分,会依据你输入的参数不同,调用不同的函数。
在C中只好分别起不同的名字,没有别的处理方法。
2)运算符重载
运算符重载只是为了满足普通的运算符运用的习气而又不会呈现错误。
C中不支持运算符重载,能够定义一个函数完成该功用。
这是普通类的修正。
七、类的继承
1)单继承
假如类之间有继承关系,先将基类依照普通类的改法,修正好。然后将基类的定义局部全部拷到子类的前头。除了将基类的结构函数名改为子类结构函数名外,不能够将基类定义的局部作其他改动。并在结构函数里调用基类的结构函数,然后假如子类掩盖了基类的函数,则要把该函数指针重定向到子类函数。这是为了坚持类的继承带来的动态联编的特性。
类之间的继承关系是复杂且多变的,为了保证基类在一切子类中的独一而且便当修正,最好的办法就是把基类的构造体局部做成宏,在子类中直接运用即可。
2)多继承
我个人以为多继承是最好不要用,他会带来一些问题,会呈现多个继承途径的问题。除非是为了便当编程而运用的,如继承接口等等。
多继承也是能够改的,将多个基类的成员全部拷到子类里,遇到反复的成员名,则在前面加上前缀来区别,当然这个指的是基类之间有相同的,假如是派生类和基类之间有重名的,则会掩盖基类。
八、其他
以上就是C++中主要的与C的区别最大而且最常用的特性及修正办法。其他的还有一些比方模板的运用等等,这些都是为了便当编程,复用代码。C中没有,只好本人写多个函数来分别完成。另外还有参数列表里的&符号要用指针替代,缺省值也要去掉,而在调用的时分要留意将缺省值写上。
到此这篇关于如何把C++的源代码改写成C代码的文章就引见到这了,更多相关C++的源代码写成C代码内容请搜索软件开发网以前的文章或继续阅读下面的相关文章希望大家以后多多支持软件开发网!