1.为了提高生产效率,我们使用别人代码库,库就是别人写好的一些代码,按照某种方式包装在一起。
2.一个库通常以一个头文件的形式给出一组函数,但是通常的话还有一些比函数(行为,动作)更重要的东西,一些特征属性(颜色,大小,质量),他们是以数据的形式表现的。在C库的头文件中,我们就定义可一个struct来表示这些特征属性。在C库中,都是一组struct和作用在它们之上的一组函数。
3.动态内存分配 在C++中用new Type 返回Type型的指针, 数组的释放delete []myarray ;new int myarray[10];
4.在C中,编译器会猜测一个函数像什么(这个特征不严格),但是他不会猜测一个结构,所有使用库结构的地方,必须加入头文件。
5.编译的时候,他是逐个单元编译的,它只知道这个单元,这个时候包含的头文件给出的声明信息非常重要,他会影响程序的翻译。比如一个头文件中声明了一个函数void f(float);这个时候,在这个文件中,如果一个整型调用这个函数,编译器根据声明就会提升。如果没有包含声明,C编译器会自己假设有一个函数void f(int);最后会链接到void f(float)么?可以通过_f_float与_f_int区别么????(C中都翻译为_f)
6.调用链接不正确很难发现,如果有几个厂家提供库中有相同名字的不同函数,程序开发就不好处理。名字冲突是一个问题。我们的目标是能够准确的链接和翻译每一个单元。
7.第一个,给函数翻译加参数,第二个,C++,把函数和结构相连,写入结构。对象的思想就出现了。C++就是把函数当做结构的一个成员。而且,这些函数自动的知道的结构地址。C++要求必须有声明。
8.作用域解析运算符:: CStack::init()
9.在C++中,头文件的声明是必须的,不能调用未声明的函数。而且结构中的函数使用成员时,隐藏的是知道结构的地址this(它产生struct的地址)。
10.在C++中允许将任何类型的指针赋值给void*(这是void*的意图,用来存放任何类型的指针),但是不能把void*赋值给其他类型的指针。因为这样就有调用可能struct逻辑不存在的成员函数。
11.在C中。struct只是分装了数据,他是数据的包,这样,编程起来方便了很多,但是C++把函数放入这个结构包中,就很像我们思维中的事物的概念了。它既描述了事物的特征属性,又能描述这个事物的行为。这样就形成了一个对象的概念,对象是一个独立的,捆绑的实体,有自己的属性和行为。
12.C++把函数写入结构的是基于对象,而不是面向对象的,这个问题就是面向对象的各种语言之间的范畴问题。
13.抽象数据类:是一种区别于基本内嵌的类型的一种概念,其实float也看以看做是抽象的,它有尾数,符号位,指数,这个只是一种相对的概念,我们的现实中的问题大部分都是抽象的复杂的数据类型。C++的捆绑封装形成的这种结构,带有他自身的一些行为函数,就形成了一个数据类型的概念。编译器可以把它可以根据这些检查这个类型个的应用,我们就把问题提升到一个更高的问题讨论了。
14.对象的细节
对象应当多大和它应当像什么?对象和C的struct一样,一个对象的大小是它的所有数据成员的大小,不包括函数。有时候会有些许的调整,为了边界对齐和寻址方便快捷。
15.头文件,正确的组织代码和头文件是很重要的,头文件中,只有声明,不包含代码和其他创建变量之类的,因为它会被包含到多个翻译单元中,如果一个标识符被多次定义,就会编译错误。但是可以在头文件中定义文件静态变量,这种情况是允许的(但是每个包含头文件的编译单元中都会有一个这个静态变量的拷贝,其实是不同的东西,static是文件内有效的意思,不同的文件中可以有相同的标识符的static变量)。就是我们不能引起歧义,要遵从编译器的规则。
16.重声明函数是可以的,只要两个函数的声明匹配就可以。但是不允许重声明结构体,那样的话就是可以使用给不同的类型定义相同的名字,这显然是错误的,应为一个class A这个类型必须是固定的,不然没法链接,这个书中写的是机器人翻译。然后这个时候就引出了#ifdef#ifndef#endif预处理。对于包含接头的头文件,应当检查这个头文件是不是已经包含在特定的CPP文件中了。这个需要测试预处理器的标记来检查,如果这个标记没有,则这个文件没有被包含,应当设置他,并声明这个结构。如果这个标志已经有了,这表示已经声明了这个结构类型,所以应当忽略这段声明它的代码。
#ifndef HEAD_FLAG
#define HEAD_FLAG
//类型在此间声明
#endif
17.头文件中的名称空间
在头文件中不要使用,一旦使用等于是所有包含此文件的cpp都对可以使用这个空间的名称,这雨名称空间的保护初衷是相悖的。
18.嵌套结构:结构中包含小的结构
//下堆栈,结构链表,嵌套结构 #ifndef STACK_H #define STACK_H struct Stack{ struct Link{ void* data; Link* next; void initialize(void* dat,Link* nxt); }*head; void initialize(); void push(void* data); void* peek(); void* pop(); void cleanup(); }; #endif
#include"Stack.h" #include"required.h" using namespace std; void Stack::Link::initialize(void* dat,Link* nxt) { data = dat; next = nxt; } void Stack::initialize() { head = 0; } void Stack::push(void* dat) { Link* newLink = new Link; newLink->initialize(dat,head); head = newLink; } // /* void* Stack::peek() { require(head!=0,"Stack empty"); return head->data; } // */ void* Stack::pop() { if(head==0) return 0; void* result = head->data; Link* oldHead =head; head = head->next; delete oldHead; return result; } void Stack::cleanup() { require(head==0,"Stack not empty"); }
#ifndef REQUIRE_H #define REQUIRE_H #include <cstdio> #include <cstdlib> #include <fstream> #include <string> inline void require(bool requirement, const std::string& msg = "Requirement failed") { using namespace std; if (!requirement) { fputs(msg.c_str(), stderr); fputs("\n", stderr); exit(1); } } inline void requireArgs(int argc, int args, const std::string& msg = "Must use %d arguments") { using namespace std; if (argc != args + 1) { fprintf(stderr, msg.c_str(), args); fputs("\n", stderr); exit(1); } } inline void requireMinArgs(int argc, int minArgs, const std::string& msg = "Must use at least %d arguments") { using namespace std; if(argc < minArgs + 1) { fprintf(stderr, msg.c_str(), minArgs); fputs("\n", stderr); exit(1); } } inline void assure(std::ifstream& in, const std::string& filename = "") { using namespace std; if(!in) { fprintf(stderr, "Could not open file %s\n", filename.c_str()); exit(1); } } inline void assure(std::ofstream& out, const std::string& filename = "") { using namespace std; if(!out) { fprintf(stderr, "Could not open file %s\n", filename.c_str()); exit(1); } } #endif
#include "Stack.h" #include "required.h"//#include "./required.h" //ok Linux//#include "../required.h" //error #include <fstream> #include <iostream> #include <string> using namespace std; int main(int argc, char* argv[]) { requireArgs(argc, 1); // File name is argument ifstream in(argv[1]); assure(in, argv[1]); Stack textlines; textlines.initialize(); //初始化head==0 string line; // Read file and store lines in the Stack: while(getline(in, line)) textlines.push(new string(line)); // Pop the lines from the Stack and print them: string* s; while((s = (string*)textlines.pop()) != 0) { cout << *s << endl; delete s; //释放new string(line) 的内存 } textlines.cleanup(); } ///:~
19.全局作用域解析 前面加 ::var ::fun()
var = 1; fun() 这种事调用默认的局部成员和函数
20.C++的基本方法就是把函数加入结构内部,结构的这种类型形成了抽象数据类型,用这种结构创建的变量称为这个类型的对象或实例。