DSP

C++比C多出的一些特殊问题

2019-07-13 16:41发布

个人属于C++新手,在学习过程中,针对目前发现的问题做一个简要的总结,目前还没有做过大的项目和工程,部分理解可能存在偏差。有问题的地方请指出。 本人从单片机和C进入编程世界,从事过单片机、DSP、音频DSP(软件)、linux驱动等开发,这部分主要是基于C进行的开发。新的工作是C++方面的,目前看了一些书籍和视频,结合以前自己学习的内容,总结出来的点有 1.C和C++的基础语法是类似的   这么说是因为,C++除了比C多出的部分外(主要是为了面向对象而添加的技术或者语法规则),剩余的部分语法规则是一样的,因而代码表现上没有很大差异。当然,设计的思维还是存在很大差异。 2.C比C++更节省内存,但C要完成一些C++的功能需要更复杂的逻辑来模拟   C++的继承、一些成员等,在创建每个class实例时都会创建一个,即使我们有时在继承中根本不会使用到,这就造成了一定的内存资源浪费。当然,这在普通的PC上一般体现不是很明显,可是如果实在资源紧张的嵌入式环境中,问题就变得比较明显了。   一般而言,小型嵌入式系统(单片机)有时也支持C++开发,例如stm32等(cm3、cm4、cm7的gcc编译器支持编译C++),我不知道这些编译器是否对这种情况下的C++代码进行优化,但是可以肯定的是,我用C++写出的代码和C写出的代码都完成一个led控制的情况下,C++生成的资源占用要大一些。  不过只要不是大吞吐量和高缓存的程序,代码实际占用的空间不会夸张的高,64KB的内存的单片机完全可以实现一个较为复杂的逻辑了。在2MB左右的内存配置情况下,一般单片机上面的开发没有太多限制。  在进行linux驱动和内核开发定制的时候,学习内核代码可以发现,其还是尽量用C去模拟和构造C++的class技术和方法,C++中的class成员函数一般声明了即可,用C进行构造时,需要先在struct中声明函数指针,将函数指针指向某个函数,这后面部分的工作通常需要显示的调用。linux驱动中的做法,一般是声明一个函数xxxx_init或者xxxx_probe或者将某个函数注入到全局的函数队列中,在开机时,让CPU从这部分队列的开始处依次执行对应的函数,从而达到目的,当然也包含了部分硬件必须的初始化工作。从类的角度来说,这个要比C++在编译期间就搞定要复杂一些。另外C模拟C++的技术在数据访问控制上明显乏力,有时会引发一些安全性问题。 3.C++比C多出来的部分  个人感觉主要还是OOP部分的技术,例如class的相关技术、重载、虚方法等等,这只是初级的差异,在泛型编程上面,STL,以及一些异常调试技术。   这里要说一下STL,STL是惠普公司开发的,后来经过调整、优化,发展成了今天的STL。STL可以说是C++比较卓越的一个成果。 4.设计思维的差异   C++代码设计思维上面,要重视如何管理数据、管理class之间的逻辑关系、以及管理class的设计。需要对事件所需的数据模型进行建模、抽象,这个可能需要长期的经验积累,而且对于任何一种面向对象语言来说,应该都是非常重要的。  C有些人喜欢玩奇淫技巧,虽然我个人比较反感这种,但是不得不说,奇淫技巧的目的还是在于提高效率。效率代码可能是C比较重视的点。所以做C代码时,我们一般注重事件逻辑设计,就是怎么去做这件事,而不是这件事的要实现构造哪些关系出来。除了必要的数据以及数据结构以外,我们的重点是在关注,如何去实现功能---因此,大多数是在关注函数的实现上面。  举个例子来说,LCD的驱动,C++也可以写驱动。 C++情况: class lcd_drv { public: xxxxx int set_lcd_freq(); int lcd_on(); xxxx }; xxxx(各种成员方法的实现) C的情况 #define LCD_FREQ XXXX #define LCD_HEIGHT xxxx xxxxx int set_lcd_freq() { xxxx }
int lcd_on() { xxxx } 上面两种代码的区别是,前者更注重于数据关系,后者更注重于功能实现。这只是一个例子,上述代码中的C也可以声明struct结构体,把函数放进去。 这个是在长期代码积累中,形成不同风格。用C模拟C++的class有时也会造成内存浪费,在struct中声明一个函数指针是4byte,对于小资源的单片机来说,局部函数变量过多的话,有时函数栈就溢出了(部分单片机可能只有几百字节的RAM)