1.C和C++
大幅度提高生产效率的方法是使用他人的代码,也就是使用库。库是他人写好的一些代码,按照某种方式包装在一起。
首先,先来看看C语言的库。
这里的CLib.h就可以看作一个库,下图的.cpp使用了这个库。
显而易见的,在C语言使用库是复杂的。
其实,除了复杂难懂以外,C语言使用库的障碍是名字冲突(name clashes)。
由于C语言的所有符号名称都定义在一个全局命名空间中,例如对于函数,编译器编译一个单元时,只能对带有指定名字的单个函数处理。
例如,上图中的initializa()这个名字被两个库文件同时使用,在同一个处理单元中,C的编译器就会报错,即使不在同一个处理单元,连接器也会产生问题。
总而言之,在C中,往往是不允许使用包含同名的两个C库的。为了解决C中的名字冲突,C库往往会在函数名前加一个独特的前缀,例如CStash_initialize(),就尽量避免了名字冲突。
我们来看C++
首先,对于C++,函数可以放在Class的内部,作为“成员函数”
可以看到,C++不再要求传递这个结构的地址作为这个结构上运算的函数的参数,而是由编译器来做这件事。这大大简化了代码。
而且,在C++中成员函数的名字不再会和其他任何结构中的函数名称产生冲突,即便是全局函数。
但是既然如此,又产生了新的问题,我们如何区分函数属于某个函数呢?C++提供了作用域解析运算符(::),例如,如果希望指定initialize()属于Stash,就写成Stash::initialize(int size);
我们作出以下总结:在C++中,头文件可以成为函数声明的仓库。在成员函数内部,成员正常使用,不必写s->size=sz;而可以写出size=sz;这样就消除了代码量。
如果出于某种原因,我们希望处理这个class的地址,在C语言中,每个函数的第一个参数是CSttash*,这是容易的。而在C++,我们可以使用this关键字来产生这个class的地址
最后,C语言允许将任何指针传递给void*,也允许将void*给任何指针,但是在c++中,我们可以将任何类型传递给void *,但是把void*指针传递给别的值是不被允许的。
2.什么是对象
在C++中,对象是变量,是具有唯一标志符或者唯一内存地址的一块存储区域,是一块空间,可以存放数据,而且还隐含着对数据的操作。
下面,我们先对基于对象object-based和面向对象oop进行区分。
将数据连同函数捆绑在一起可以用于创建新的数据类型,这个操作叫做封装(encapsulation)基于对象只停留在将函数捆绑在数据结构的内部,也就是基本只停留在封装上,对于面向对象的三大特性,封装、继承和多态并没有很好的实现。
封装为我们提供了一种新的数据类型,我们称之为抽象数据类型(abstract data type)。
在面向对象的用法中,object.member.Function()被称为向一个对象发送消息。
3.头文件
首先需要了解,在C语言和C++中,重复声明函数是允许的(重载和重写),但是重复声明结构是不被允许的。在项目的多个cpp文件中,可能包含了几个使用相同同文件的文件,在一次编译过程中,编译器可能多次看到相同的头文件,除非特别处理,编译器将会发现结构的重声明。
所以我们对预处理器知识进行改进,例如上图,或者如下
#ifdef HEADER_FLAG
#define HEADER_FLAG
#endif
这就代表,如果标记没有设置,就会设置它,如果标记已经被设置,表明这个类型很可能被声明,就应该忽略这段代码。防止多次包含这些预处理器语句常常被称为包含守卫(include guard)
最后,我们将会多次看到using namespace std;
std是环绕整个标准C++库的命名空间,这个指令允许不限制方式的使用C++库的语句。但是不要再头文件使用这个语句。
在编写C++项目中,我们希望把类的声明放在头文件中,在具体的cpp文件中实现定义。
另外,类是可以嵌套的。例如:
我们还可以通过作用域解析符来区分同名变量、函数是哪个类的成员变量、函数亦或是全局变量、函数。
例如,上图类S中的成员函数f()内部,::就代表调用了全局函数f()和全局a,而不加解释的a就代表类S本身内部的a。
而在主函数中,不加解释的f()缺代表全局函数。
总结:
1.C语言和C++的对比区别
2.什么是对象
3.头文件和预处理器命令