站长工具seo综合查询权重,网络基础架构,wordpress的字体禁用,淘宝导购网站怎么做由于C#xff0b;#xff0b;解释器比C语言解释器占用的存储空间要大500k左右。为了节省有限的存储空间、降低成本#xff0c;同时也为了提高效率#xff0c;将用C#xff0b;#xff0b;语言写的源程序用C语言改写是很有必要的。
C#xff0b;#xff0b;与C最大的区… 由于C解释器比C语言解释器占用的存储空间要大500k左右。为了节省有限的存储空间、降低成本同时也为了提高效率将用C语言写的源程序用C语言改写是很有必要的。
C与C最大的区别就是C中的类的概念和特性将C改为C的问题就转换成如何将类化去的问题。 方法有两种
第一种是将C中的面向对象特征去掉先全部理解源代码的逻辑然后改写第二种是在C中保留面向对象的部分特征用结构体实现类的功能。
第一种方法对于类的数目很少的情况还可以如果类的数目比较多全部理解源代码然后重写就很耗时间而且很容易出错更甚者如果遇到大的项目想全部理解源代码几乎是不可能的。
如果程序中类有140多个这个时候就需要采用第二个方法了你可以一个类一个类的改没有什么太高的难度如果不是笔误的话几乎不会出错而且根本不需要理解程序逻辑也许改完后你对程序所要实现的功能还一无所知。倒不是说一无所知对大家有好处只是想说这种方法的与程序逻辑本身的无关性。
下面对C的一些特性以及如何在C里面实现或者替代作一些初步的探讨。
说明 函数Ixx为类xx的构造函数的实现 原类的成员函数改为前缀为结构体名‘_’的函数 函数指针U为原类的析构函数的声明 U结构体名称为原类的析构函数的实现 Fun-_结构体名为对该结构体成员函数指针进行指向 以后遇到上述情况将不再说明 类的成员函数和数据成员
由于struct没有对成员的访问权限进行控制必须加入额外的机制进行访问控制这样一来就使得程序复杂化了所以只能放弃访问权限的控制。
1对于类的数据成员可以直接转为C中结构体的数据成员。
2函数则需转化为对应的函数指针因为struct里不允许出现函数的声明和定义。而函数前如果有virtureinline等修饰符也要去掉如函数void funca(int a);改为void (*funca)(struct B *p,int a);大家可以看到函数指针的原型里加了一个指针struct B的指针这是因为要在函数内部对类的成员进行操作要靠该指针指定结构体的成员。在类的成员函数里实际上在参数列里也隐含有一个指向自身的this指针。
3对于静态成员则要定义成全局变量或全局函数因为结构体中不能有静态成员。 类的构造函数
类在实例化的时候会调用类的缺省构造函数在struct里要定义一个同名函数指针指向一个具有构造函数功能的初始化函数与构造函数不同的是要在初始化函数里加入进行函数指针初始化的语句。使用的时候在创建结构体变量的时候要用malloc而不是new并且这个时候要手工调用初始化函数。
如下例所示 class A{public: A(); ~A(); void func(int a); private: int b;};A::A(){ b0;} void Afunc(int a){ ba;} typedef struct classA A;struct classA{ void (*A)(struct classA *p);//构造函数指针 void (*U)(struct classA *p);//析构函数指针 void (*func)(struct classA *p,int a); int b;}; void fun_A(A *p){ p-funcclassA_func; //将函数指针初始化} void IA(A *p) //构造函数命名规则在类名前加I{ fun_A(p); p-b0; //原构造函数所作部分} void classA_func(A *p,int a){ p-ba;} 在使用的地方采用如下方式 A *s(A*)malloc(sizeof(A)); s-AIA; s-A(s); 类的析构函数
类的析构函数所做的工作是释放所占的资源。
在C中无论是哪个struct都用函数指针U替代析构函数。之所以所有的struct都用指针U是基于如下情况
如果将子类指针赋给基类指针基类指针在释放的时候不必考虑调用哪个函数名的析构函数只需调用成员函数U即可。成员函数U需要像一般成员函数一样在fun_类名()函数中指定。
类的析构函数是由系统调用的在C中则要显式调用。至于何时调用要准确判断。 类的拷贝构造函数
类的拷贝构造函数主要用途是加快以下情况下类的构建速度
1. 作为参数传给函数。additemItema
2. 作为函数返回值。
3. 实例化类时作参数。
这三种情况下都是由系统直接调用类的拷贝构造函数而不是构造函数。
注意CD不会调用拷贝构造函数这种情况下使用的是重载‘’运算符的方法。(详见运算符重载)
由于C中定义struct变量的时候使用的全部是指针不会用到拷贝构造函数所以暂不考虑。对于原来函数参数或者返回值需要类变量的要全部转化为类指针的方式。实例化类时作参数的情况可以通过另外定义一个带参数的构造函数来解决。 类的内联函数和虚函数
内联函数和虚函数的修饰符inline、virture要全部去掉。内联函数体则要去掉将内联函数在外面定义成一个函数。如下 class B{ ... virtual void funb(); inline int add() const {return ab;}; private: int a; int b; ...}
改为 typedef classB B;struct classB{ … void (*funb)(struct classB *p); int (*add)(struct classB *p); int a; int b;} void classB_funb(B *p){ …} int classB_add(B *p){ return p-ap-b;} void fun_classB(B *p){ … p-funbclassB_funb; p-add classB_add;} 重载
类中重载有函数重载和运算符重载两种
1函数的重载
函数重载满足的条件是函数名相同参数个数或者参数类型不同。
这样在调用的时候会根据你输入的参数不同调用不同的函数。
在C中只好分别起不同的名字没有别的解决办法。
2运算符重载
运算符重载只是为了满足一般的运算符使用的习惯而又不会出现错误。
C中不支持运算符重载可以定义一个函数实现该功能。
这是一般类的修改。 七、类的继承
1单继承 如果类之间有继承关系先将基类按照一般类的改法修改好然后将基类的定义部分全部拷到子类的前头。
除了将基类的构造函数名改为子类构造函数名外不可以将基类定义的部分作其他改动。并在构造函数里调用基类的构造函数然后如果子类覆盖了基类的函数则要把该函数指针重定向到子类函数。这是为了保持类的继承带来的动态联编的特性。
类之间的继承关系是复杂且多变的为了保证基类在所有子类中的唯一而且方便修改最好的方法就是把基类的结构体部分做成宏在子类中直接使用即可。
2多继承 我个人认为多继承是最好不要用他会带来一些问题会出现多个继承路径的问题。除非是为了方便编程而使用的如继承接口等等。 多继承也是可以改的将多个基类的成员全部拷到子类里遇到重复的成员名则在前面加上前缀来区别当然这个指的是基类之间有相同的如果是派生类和基类之间有重名的则会覆盖基类。
其他
以上就是C中主要的与C的区别最大而且最常用的特性及修改方法。
其他的还有一些比如模板的使用等等这些都是为了方便编程复用代码。C语言中没有只好自己写多个函数来分别实现。
另外还有参数列表里的符号要用指针替代缺省值也要去掉而在调用的时候要注意将缺省值写上。