C++ 我想这样用(三)

话接前篇,继续谈在C++环境下使用C风格编程时的注意点:

6.关于原型的声明

在C里,调用一个未声明的函数是允许的,但是在C++里,必须先声明才能调用函数。另外,如果函数的参数是空的,那么在c里面是未定义参数列表,在C++里面却是void。

Example

extern void func();
          ....
          sub();
          func(0);

所以上面的sub();在c里对,在C++里就错了,func(0);也是一样的。

我的建议是:任何C语言的编程典范,都是建议函数先声明后使用的,在C99之后更是这样,如果你不是上个世纪来的编程大佬,请不要再使用K&R的风格了。。

7.关于关键字

下面这些关键字是C++里有但是C里面没有的:

asm             bool            catch           class
          const_cast      delete          dynamic_cast    explicit
          false           friend          inline          mutable
          namespace       new             operator        private
          protected       public          reinterpret_cast
          static_cast     template        this            throw
          true            try             typeid          typename
          using           virtual

我列出这些的意思不是说要花时间来掌握他们,因为我的原则在C++ 我想这样用(一)就说过了,我只用和对象有关的极少的一部分C++的东西。

我的意思是指,不要再把这些东西用作标识符了,原因不说即明。或许你觉得这条很多余,但是如果你真的像我一样很喜欢用C来模拟实现面向对象,那么看看你以前的代码吧,你就知道这条多么重要了。。。。。。

8.关于内存管理

在上一篇中就有好心吧友提醒我关于new的问题,没错接下来我就说说把,先看一例:

Example

int (*p)[10];
          p = (int (*)[10])malloc(sizeof(*p));
          ....
          delete p;

  
          /* The delete expression has undefined behavior. */

没错,如果你用delete干掉一块malloc分出来的内存空间,天知道会发生什么,这全看编译器的心情。说白了人家new和delete是一对,malloc(or calloc or realloc)和free是一对。不要乱配。你在想什么呢?没错!和我一样!咱们就不用什么new了,反正也不是C的东西,还是malloc来得舒心,哈哈!

不过很可惜不行,看了下面的事实你就知道了:

  1,malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
  2,对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
  3,因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
  4,C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。
  5、new可以认为是malloc加构造函数的执行。new出来的指针是直接带类型信息的。而malloc返回的都是void指针。

没错,基本上new=(malloc+执行构造函数+类型转换),我们要面向对象,也就必须用new和delete,我的建议是两条路任你选:

1.除了对象用new和delete,其他情况依旧用你最爱的malloc和free

2.反正new基本可以认为内部实现就调用了malloc,所以以后就全用new和delete吧

9.关于const的类型限定

这还是一个关于默认的问题,如果你在一个文件里写

  const int pi = 3.14;

那么默认的连接属性是:

  extern const int pi = 3.14; (in C)

  static   const int pi = 3.14; (in C++)

多敲一点不会死,我的一贯做法是,不管编译器老人家帮不帮你擦屁股,我肯定是自己擦干净!!

10.关于标准库

没错,标准库是和语言最近的东西,基本上我们每天都在用,于是来到了C++环境,这也成为了一个问题。幸好C++在这方面做的很到位,几乎在主流的平台的C++编译器上,你可以放心使用全部的C标准库。

在这个系列里,没有.h结尾的头文件(包括那些cstdio什么的。。)是绝对禁用的,如果你感到不适,请不要在意,因为这篇文章是写给“重度强迫症+C脑残粉”的。很庆幸你不是=  =!

如果你不幸中枪,那么恭喜你,下面这些是你最喜欢的:

C89中有15个标准头文件:

<assert.h> 、<ctype.h> 、 <errno.h>、 <float.h>、 <limits.h>、 <locale.h>、

<math.h> 、 <setjmp.h> 、<signal.h> 、<stdarg.h>、<stddef.h> 、

<stdio.h>、 <stdlib.h>、 <string.h>  、<time.h>

C95增加了3个标准头文件:<iso646.h>、<wchar.h>、<wctype.h>

C99增加了6个标准头文件:

<complex.h> 、<fenv.h>、<inttypes.h> 、<stdbool.h> 、<stdint.h>、<tgmath.h>

关于注意点,我就写这么10点了,我知道其实还有很多很多,尤其是C99的出现使得情况更严重。如果大家有补充或建议和纠正,请积极留言哦。

此外,我向大家推荐clean-c这个东西,可以说是C与C++的交集。算不上取C语言的子集,也就是对C特性做一些更严格些的约束条件,使得这些特性能同时符合标准C语言和标准C++语言的规定。用这个东西写出来的代码可移植性非常高,据说Lua就是用它写的呢。不过我没找到clean c的正规文档或项目主页,谁知道的,望分享啊。。

后续的文章就是具体的面向对象的部分了,究竟怎么组织我还在构思。。。。。

上一篇:Linux init 0-6 启动级别


下一篇:Android 7.0 启动篇 — init原理(二)(转 Android 9.0 分析)