CPP 4. 复合类型 2020-10-15 浏览量 579 暂无评论 # 第4章 复合类型 最深远的复合类型是类。 ## 4.1 数组 ### 4.1.1 声明方法 ```cpp typeName arrayName[arraySize]; short months[12]; //从0开始编号 ``` 注意: 1. 编译器不会检查使用的下标是否有效,当下标超出数组范围时,编译器并不会报错,但是程序运行后,会引发问题,也可能导致程序异常终止; 2. 存储多个同类型的值; 3. 在内存中是连续的。 ### 4.1.2 初始化规则 1. 只有在定义数组时才能使用初始化,不能先声明再直接对整个数组赋值,但是可以使用下标分别给数组中的元素赋值; ```cpp int card[4] = {3, 6, 8, 10}; // okay int hand[4]; // okay hand[4] = {5, 6, 7, 9}; // not allowed hand = cards; // not allowed hand[0] = 3; // okay ``` 2. 初始化数组时,提供的值可以少于数组的元素数目,剩余的会被编译器自动设置为0,这在将数组中所有元素都初始化为0时很有用; 3. 如果初始化数组时方括号内([])为空,C++编译器将会自动统计元素个数(在初始化数组时通常别这样做,但初始化字符串时这样很方便); 4. 初始化数组时,可省略等号(=)(C++11); 5. 初始化数组时,可不在大括号内包含任何东西,默认为0(C++11); 6. 初始化时禁止缩窄转换(C+11)。 **ps:** C++标准模板库提供了数组的替代品--模板类`vector`,C++11新增了模板类`array`,比内置复合类型数组更复杂、更灵活。 具体怎么灵活呢? ## 4.2 字符串 ### 4.2.1 字符串初始化 注意: 1. 字符串在内存中也是连续的,可以存储在char数组中; 2. C-风格字符串以空字符(null character)结尾,被写作\0,其ASCII码为0,用来标记字符串的结尾,不是空格; 3. 使用引号括起的字符串常量,隐式地包括结尾的空字符; 4. `''`和`""`的区别很大,一个是字符常量,一个是字符串常量,如`"S"`表示两个字符(字符S和\0)组成的字符串。 ```cpp char dog[8] = {'b', 'e', 'a', 'u', 'x', ' ', 'I', 'I'}; // not a string char cat[8] = {'f', 'a', 't', 't', 'e', 's', 's', 'a', '\0'}; // a string char fish[] = "Bubbles"; // a string char shirt_size = "S"; // illegal type mismatch ``` ### 4.2.2 字符串拼接 😄任何两个由空白(空格、制表符、换行符)分隔的字符串常量都将自动拼接成一个,第一个字符串的\0字符将被第二个字符串的第一个字符取代。 ### 4.2.3 在数组中使用字符串 **string.cpp** ```cpp #include #include // for strlen() function int main() { using namespace std; const int Size = 15; char p1[Size]; char p2[Size] = "却又吹得让它慌张\n"; cout << "你问风为什么托着候鸟飞翔, " << p2; cin >> p1; cout << "却也湿透她的衣裳\n"; cout << "你问我为什么还是不敢放下, " "明知听不到回答\n"; } ``` 注意: 1. `strlen()`函数返回存储在数组中的字符串的长度,只计算可见的字符,不包含空字符; 2. `sizeof()`运算符统计整个数组的长度。 ### 4.2.4 字符串的输入 **insre1.cpp** ```cpp #include int main() { using namespace std; const int ArSize = 20; char name[ArSize]; char dessert[ArSize]; cout << "Enter your name:\n"; cin >> name; cout << "Enter your favorite dessert:\n"; cin >> dessert; cout << "I have some delicious " << dessert; cout << " for you, " << name << ".\n"; return 0; } ``` >Enter your name: >**Jineng Dreeb** >Enter your favorite dessert: >I have some delicious Dreeb for you, Jineng. 在本例中,都没有对“Enter your favorite dessert:”作出反应,程序就已经显示出来了,为什么呢?这关系到`cin`如何确定已完成对字符串的输入。 由于不能通过键盘输入空字符,因此`cin`使用空白(空格、制表符、换行符)来确定字符串的结束位置,`cin`在获取字符数组时只读取一个单词,然后将该字符串放在数组中,并自动在结尾添加空字符,后面的单词留在输入队列中,等待下一次读取。 ### 4.2.5 每次读取一行字符串输入 C++常使用指针来处理字符串。 注意: 1. `cin.getline()`每次读取一行,读到换行符,随后丢弃换行符,保存时将换行符替换为空字符; 2. `cin.get()`读到换行符,将换行符留在队列中; 3. `cin.get()`用来检查错误更方便,通过读取下一个字符是不是换行符可以知道之前读的字符串是否超出了数组的长度; 4. *`cin.get()`* 在读取空行后将设置失效位(failbit),接下来的输入将会被阻断(**直接回车,程序直接退出了**),但可用`cin.clear()`来恢复输入; 5. 当输入的字符串比分配空间长时,都会把余下的字符留在输入队列中,而 *`cin.getline()`* 还会设置失效位,并关闭后面的输入(**直接回车,程序直接退出了**)。 以下语句等价: ```cpp cin.getline(name1, ArSize).getline(name2, ArSize); cin.get(name1, ArSize).get().getline(name2, ArSize).get(); // cin.get()读取下一个字符(即使是换行符) ``` ##### 4.2.6 混合输入字符串和数字 如下程序会出现问题,用户没有输入地址的机会。因为cin读取年份后,将回车键生成的换行符留在了输入队列,getline会把换行符当作空行赋给address数组,可以在cin后加get。 ```cpp int year; cin >> year; char address[80]; cin.getline(address, 80); ``` ## 4.3 String类 **特点:** 1. 自动调整长度; 2. 使字符串操作更容易。 ### 4.3.1 初始化 ```cpp string str1; cin >> str1; // str1开始长度为0,但将输入读取到str1中时,将自动调整str1长度 string str2 = "panther"; // C++11 char first[] = {"JHAN"}; char second[] {"JHAN"}; string third = {"JHAN"}; string fourth {"JHAN"}; ``` ### 4.3.2 赋值、拼接和附加 不能将一个数组赋给另一个数组,但是可以将一个string对象赋给另一个string对象。 ```cpp string str3; str3 = str1 + str2; // 拼接str1和str2给str3,cstring strcpy (这个没法自动调整长度,可用stmcpy接受第三个参数) str1 += str2; // 把str2加到str1后面,cstring strcat (这个没法自动调整长度,可用stmcat接受第三个参数) string str; getline(cin, str); ``` ##### 4.3.3 原始字符串(C++11) ```cpp cout << R"(jhan "jhan" "\n")" << '\n'; cout << R"+*("(jhan)", jhan)+*" << '\n'; ``` >jhan "jhan" "\n" >"(jhan)", jhan ## 4.4 结构简介 **特点:** 1. 存储多种类型的数据; 2. 使用运算符(.)来访问各个成员; 3. 外部声明(位于函数外面)和内部声明(位于main()函数内部)的作用域,若内部声明和外部声明名称重复,则在函数内部以内部声明为准; 4. 对结构的操作与内置类型相似(例如作为参数传递,作为返回值,成员赋值)。 ```cpp // 结构描述: struct inflatable { char name[20]; float volume; double price; }; // 声明结构变量 struct inflatable goose; // C需要使用关键字struct inflatable vincent; // C++可以省略关键字struct // 初始化结构变量 inflatable guest = { "jhan", 1.88, 29.99 }; // 有些实现需要用 static inflatable guest,为什么呢? inflatable duck {"yuli", 0.12, 9.98}; inflatable duck {}; // 都被设置为零 // 可以同时完成定义结构和创建结构变量的工作 struct perks { int key_number; char car[12]; } mr_smith, ms_jones; // 甚至可以同时初始化 struct perks { int key_number; char car[12]; } mr_glitz = { 7, "jhan" }; // 还可以声明没有名称的结构类型,但需要同时定义变量 struct { int x; int y; } position; /******** 结构数组 ********/ inflatable gifts[100]; // array of 100 inflatable structures inflatable guests[2] = { {"Bambi", 0.5, 21.99}, {"Godzilla", 2000, 565.99} }; // 位字段,指定占用特定位数的结构成员(使得创建与某个硬件设备上的寄存器对应的数据结构特别方便) // 字段的类型应为整型或枚举 struct torgle_register { unsigned int SN : 4; // 4 bits for SN value unsigned int : 4; // 4 bits unused bool goodIn : 1; bool goodTorgle : 1; }; torgle_register tr = {14, true, false}; ``` ## 4.5 共用体 **特点:** 1. 能够存储不同类型的数据类型,但只能同时存储其中一种类型; 2. 共用体的长度为其最大成员的长度(那还怎么节省空间?) ```cpp union one4all { int int_val; long long_val; double double_val; }; struct widgrt { char brand[20]; int type; union id { long id_num; char id_char[20]; } id_var; }; ... widget prize; ... if (prize.type == 1) cin >> prize.id_val.id_num; else cin >> prize.id_var.id_char; // 匿名共用体,共用体成员被视为变量prize的成员,它们的地址相同,不需要中间标识符id_val struct widgrt { char brand[20]; int type; union { long id_num; char id_char[20]; }; }; ... widget prize; ... if (prize.type == 1) cin >> prize.id_num; else cin >> prize.id_char; // 可以使用one4all变量来存储int、long或double,条件是在不同的时间进行 one4all pail; pail.int_val = 15; pail.double_val = 1.38; ``` **作用(使用场景):** - [ ] 疑问: 到底怎么节省的?从下面的程序运行结果来看,所占空间并没有随使用的变量数据类型而动态变化啊。常用于节省内存。当数据项使用两种或更多种格式(但不会同时使用)时,可节省空间。 ```cpp #include union test { int a; double b; }; int main() { using namespace std; test jhan; jhan.a = 4; cout << "size of int is " << sizeof(int) << endl; // 4 cout << "size of double is " << sizeof(double) << endl; // 8 cout << "size of jhan is " << sizeof(jhan) << endl; // 8 cout << "size of test is " << sizeof(test) << endl; // 8 jhan.b = 8.23; cout << "size of jhan is " << sizeof(jhan) << endl; // 8 cout << "size of test is " << sizeof(test) << endl; // 8 cin.get(); } ``` ## 4.6 枚举 **作用:** 1. 创建符号常量,代替const; 2. 枚举量是整型,可被提升为int类型,但int类型不能自动转换为枚举类型; 3. 在算术表达式中,枚举将被转换为整数,得到的类型为int,不能直接赋给枚举变量 ```cpp // 让spectrum成为新类型的名称;spectrum被成为枚举(enumeration); // 将red、orange、yellow等作为符号常量,对应整数值0~7,这些常量叫作枚举量 enum spectrum {red, orange, yellow, green, blue, violet, indigo}; enum {red, orange, yellow, green, blue, violet, indigo}; // 一些限制 spectrum band; band = blue; // valid band = 2000; // invalid band = orange + red; // invalid int color = blue; // valid, promoted to int band = 3; // invalid band = spectrum(3); // valid band = spectrum(4003); // undefined, result not sure color = 3 + red; // valid // 设置枚举量的值 enum bits{one = 1, two = 2, four = 4, eight = 8}; bits myflag; myflag = bits(6); // valid // first = 0, third = 101 enum bigstep{first, second = 100, third}; // zero, null = 0; one, numero_uno = 1 enum {zero, null = 0, one, numero_uno = 1}; // 枚举的取值范围,允许在取值范围内使用强制类型转换将整数值给枚举变量 上限:大于最大值的最小的2的幂减1 下限:若最小值不小于0,则下限为0;否则。小于最小值的最大的2的幂(加负号)加1 ``` ## 4.7 指针和自由空间 计算机程序在存储数据时必须跟踪的3种基本属性: 1. 信息存储在何处; 2. 存储的值为多少; 3. 存储的信息是什么类型。 达到这种目的的一种策略:定义简单变量,指出值得类型和符号名,让程序为值分配内存,并在内部跟踪该内存单元,**这时值是指定的量,而地址为派生量**。 **为什么要使用指针?** 使程序能够在运行阶段动态分配内存(配合new),节省空间,而不是在编译阶段就将所需的空间按可能的最大值确定下来。**这时地址为指定的量,而值为派生量**。 **特点:** 1. 改变指针所指的地址处的值,此处的变量值也变; 2. 尽管指针有许多不同的类型,但是所有指针变量本身的长度都是一样的,只是它们指向的数据类型不同; 3. 指针名可以用来加减,实现地址偏移(一次偏移一个类型长度); **注意点:** 1. 一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址,错误示范:`long * fellow; *fellow = 223323;`地址不明确,可能导致一些**最隐匿、最难以跟踪**的bug; 2. 地址本身只指出了对象存储地址的开始; 3. 内存耗尽,new引发异常; 4. new创建数组时,返回第一个元素的地址给指针; 5. 只有在使用了new后,才能使用delete,将它用于new分配的内存; 6. 不能使用sizeof运算符来确定动态分配的数组包含的字节数,但是程序确实跟踪了分配的内存量(只是信息不公用) ```cpp // 指针与地址 #include int main() { using namespace std; int a = 6; // *运算符两边的空格是可选的 // C: int *ptr; // C++: int* ptr; int * p_a; // 下面的声明创建一个指针(p1)和一个int变量(p2),对每个指针变量名,都需要使用一个* int* p1, p2 p_a = &a; /* a == *p_a &a == p_a */ *p_a = *p_a + 1; // a = 7 // 指针和数字 int * pt; pt = 0XB8000000; // type mismatch pt = (int *) 0XB8000000; // type now match // 使用new来分配内存(在运行阶段分配未命名的内存以存储值) // 常规变量声明从栈(stack)分配内存,new从堆(heap)或自由存储区(free store)分配内存 int * pn = new int; *pn = 2020; // 使用delete释放内存 int* ps = new int; int* pq = ps; cout << "ps: " << ps << endl; cout << "pq: " << pq << endl; // pd == ps delete pq; /* 如果程序只需要小型数据对象,那直接声明简单变量比使用new和指针更简单, 对于大型数据,应使用new。 在编译时为数组分配内存空间称为静态联编(static binding), 在运行时选择创建并选择长度称为动态联编(dynamic binding)。 */ // 使用new创建动态数组 // new返回第一个元素的地址,该地址被赋给指针psome int * psome = new int [10]; // 还不是占了10个int??? delete [] psome; // 指针名可以用来加减,地址偏移 double * p3 = new double [3]; p3[0] = 0.2; p3[1] = 0.5; p3[2] = 0.8; p3 = p3 + 1; // p3[0] = 0.5 p3 = p3 - 1; // p3[0] = 0.2 } ``` ## 4.8 指针、数组、指针算术 从面的例子中可以看出,我们可以像操作数组一样操作指针,原因在于指针算术和C++内部处理数组的方式。 **知识点:** 1. 整数变量加1后,其值将增加1;将指针变量加1后,增加的量等于它指向的类型的字节数; 2. C++将数组名解释为地址; 3. 对数组应用sizeof得到的是数组的长度,对指针应用sizeof得到的是指针的长度; 4. `&数组名`得到的是整个数组的地址,虽然cout输出与`数组名`的结果相同,但是它们加1后的结果不一样; 5. 数组指针:假设数组长度为20,指向数组的指针`double (*pas)[20] = &arrayName`,使用`double *pas = &arrayName`会报错;指针数组`double *pas[20]`,数组的元素是指针; 6. 在cout和多数C++表达式中,char数组名、char指针以及用引号括起的字符串常量都被解释为字符串第一个字符的地址; 7. 应使用strcpy()或strncpy()将字符串赋给数组,而不是赋值运算符; 8. 不能使用`=`将一个字符串赋给另一个字符数组或字符指针; **数组与指针** ```cpp #include int main() { using namespace std; double wages[3] = {100.0, 200.0, 300.0}; short stacks[3] = {3, 2, 1}; // 两种获取数组地址的方式 double * pw = wages; short * ps = &stacks[0]; // 这也说明数组的地址是第一个元素的起始地址 cout << "wages: " << wages << endl; cout << "&wages: " << &wages << endl; // 数组的地址,double (*pas)[20] = &tell cout << "wages + 1: " << wages + 1 << endl; cout << "&wages + 1: " << &wages + 1 << endl; cout << "wages[0]: " << wages[0] << endl; cout << "*wages: " << *wages << endl; cout << "*(&(wages[0])): " << *(&(wages[0])) << endl; cin.get(); /* wages: 0x70fdf0 &wages: 0x70fdf0 wages + 1: 0x70fdf8 &wages + 1: 0x70fe08 wages[0]: 100 *wages: 100 *(&(wages[0])): 100 */ } ``` **使用new创建动态结构** 创建动态结构时,不能将成员运算符句点用于结构名,因为这种结构没有名称,只是知道它的地址。这种情况有个专门的运算符`->`。 ```cpp struc things { int good; int bad; }; things grubnose = {3, 453}; things *pt = &grubnose; // grubnose.good == pt->good == (*pt).good ``` **一个使用new和delete节省内存的示例** ```cpp #include #include using namespace std; char * getname(void); int main() { char *name; name = getname(); cout << name << " at " << (int *) name << endl; delete [] name; name = getname(); cout << name << " at " << (int *) name << endl; delete [] name; cin.get(); cin.get(); return 0; } char * getname() { char temp[80]; cout << "Enter last name: "; cin >> temp; char * pn = new char[strlen(temp) + 1]; strcpy(pn, temp); return pn; } ``` **自动存储、静态存储、动态存储** C++的3中管理数据内存的方式,C++11新增了第四种类型:线程存储。 1. **自动存储** **生命周期:** 在函数内部定义的常规变量使用自动存储空间,被称为自动变量,意味着它在所属的函数被调用时自动产生,该函数结束时消亡。实际上,自动变量是一个局部变量,其作用域为包含它的代码块。 **存储位置:** 通常存储在栈中,后进先出(LIFO)。 2. **静态存储** **生命周期:** 整个程序执行期间都存在。使变量成为静态的两种方式:在函数外定义它;在声明时使用关键字static。 3. **动态存储** 使用new和delete实现。它们管理了一个内存池,这在C++中被称为自由存储空间(free store)或堆(heap),该内存池与用于静态变量和自动变量的内存是分开的。 注意:要养成同时使用new和delete的习惯,否则容易发生内存泄漏,**C++智能指针**有助于自动完成这种任务。 **指向指针的指针** - [ ] 为什么跟结构有关的指针前面要加关键字const呢? ```cpp struct person { int age; }; person p1, p2, p3; const person * aim[3] = {&p1, &p2, &p3}; const person ** ppa = aim; auto ppb = aim; ``` ## 4.9 数组的替代品:模板类vector和array **模板类vector** `vector vt(n_elem);` 类似于string类,是一种动态数组。 ```cpp #include ... using namespace std; vector vi; // create a zero-size array of int int n; cin >> n; vector vd(n); // create an array of n doubles ``` **模板类array(C++11)** `array arr;` 注意: 1. 只有在C++11中,才可以将列表初始化用于vector和array对象,其他情况只能一个个赋值; 2. array对象和数组存储在相同的内存区域(栈),vector存储在另一区域(自由存储区或堆); 3. 不允许使用负索引,但使用中括号时C++不会检查,可以使用at成员函数来捕获非法索引。 - 阅读全文 -
CPP 3. 处理数据 2020-10-13 浏览量 587 暂无评论 # 第3章 处理数据 ## 3.1 强制类型转换 ```cpp // typecast.cpp -- forcing type changes #include int main() { using namespace std; int auks, bats, coots; auks = 19.99 + 11.99; bats = (int) 19.99 + (int) 11.99; // old C syntax coots = int (19.99) + int (11.99); // new C++ syntax cout << "auks = " << auks << ", bats = " << bats; cout << ", coots = " << coots << endl; ``` ## 2 auto声明(C++11) 让编译器能够根据初始值的类型推断变量的类型。 并不是为初始化声明而生的(这根本没必要),反而会让人误入歧途,只有处理复杂类型,如标准模块库(STL)中的类型时,自动推断类型的优势才能显现出来,例如: ```cpp // C++98 std::vector scores; std::vector::iterator pv = scores.begin(); // C++11 std::vector scores; auto pv = scores.begin(); ``` - 阅读全文 -
CPP 2. 开始学习CPP 2020-10-10 浏览量 701 暂无评论 # 第2章 开始学习CPP ## 2.1. 进入C++ ```cpp #include iostream int main(){ using namespace std; cout << "Come up and C++ me some time."; cout << endl; cout << "You won't regret it!" << endl; return 0; } ``` Output: > Come up and C++ me some time. You won't regret it! - 函数头 函数头“int main()”描述了函数与调用它的函数之间的接口,“int”表示函数的返回类型,“()”中的叫做形参列表,空括号意味着“main()”函数不接受任何参数,在C++中,空括号与在括号中使用“void”等效。 - 注释 C++中使用“//”进行单行注释,也能够识别C注释,C注释包括在符号“/*”和“*/”之间,可以跨越多行。 - C++预处理器 这里只讨论处理名称以“#”开头的编译指令。“#include <iostrean>”将iostream文件的内容添加到程序中,实际上,iostream文件的内容将取代程序中的代码行“#include <iostrean>”,原始文件没有被修改,而是将源代码文件和iostream组合成一个复合文件,编译的下一阶段将使用该文件。 - 头文件名 头文件也叫包含文件。C++对老式C的头文件保留了扩展名h,而C++头文件则没有扩展名。有些C头文件被转换为C++头文件,这些文件被重命名,去掉了扩展名h,并在文件名称前面加上前缀c(表明来自C语言)。对于纯粹的C++头文件,去掉h不只是形式上的变化,没有h的头文件也可以包含名称空间。 - 名称空间 为什么要使用名称空间呢?为了处理这样的问题:在同时使用两个封装好的产品时,它们都包含一个名为wanda()的函数,使编译器不知道使用哪个版本.如果不使用using编译指令,可以这样进行编码:std::cout << "Come up and C++ me some time.";std::cout << std::endl;比起直接使用using namespace std使得std名称空间中的所有名称都可用,更推荐只使所需的名称可用(大型项目时),可以通过使用using声明来实现:using std::cout; // make cout available注意:仅当头文件没有扩展名h时才是这样。 - C++源代码的格式化 标记:一行代码中不可分割的元素,如“int、(、)”;空白:空格、制表符、回车; - C++源代码风格: - 每条语句占一行; - 每个函数都有一个开始花括号和一个结束花括号,这两个花括号各占一行; - 函数中的语句都相对于花括号进行缩进;与函数名称相关的圆括号周围没有空白(为了帮助区分函数和一些也使用圆括号的C++内置结构,如循环)。 - 空行将声明语句与程序的其他部分分开(C常用的方法,C++中不那么常见); - 通常把函数原型放在main()定义之前; - 待补充... ## 2.2. C++语句 ```cpp #include iostream; int main(){ using namespace std; int carrots; carrots = 25; cout << "I have "; cout << carrots; cout << " carrots."; cout << endl; carrots = carrots - 1; cout << "Crunch, crunch. Now I have " << carrots << " carrots." << endl; return 0; } ``` Output: > I have 25 carrots. Crunch, crunch. Now I have 24 carrots. - 声明语句和变量 声明有定义声明和引用声明。程序中的声明语句叫做定义声明,它使编译器为变量分配内存空间,而引用声明命令计算机使用在其他地方定义的变量。此处的“int carrots;”为定义,它提供了需要的内存以及该内存单元的名称。 - 赋值语句 赋值语句将值赋给存储单元。carrots = 25;同C一样,可以连续使用赋值运算符,且各变量的内存空间是独立的。 注意:与python不同,C++的连续赋值的变量是独立的,因为事先进行了声明,已经开辟了内存空间,而python连续赋值的变量指向同一个内存空间,修改其中一个变量,另一个变量的值也会变。 - 返回语句 ### 2.3. 其他C++语句 - 消息语句:cout - 消息语句:cin - 类 对象之于类就像变量之于类型,类描述了一种数据类型的全部属性(包括可使用它执行的操作)。 - 函数调用 - 函数原型 ### 2.4. 函数 使用函数前要进行函数声明,如double sqrt(double);,可将函数声明写在头文件中,然后包含头文件(注意头文件和库文件的区别)。 - 阅读全文 -
CPP 1. 预备知识 2020-10-09 浏览量 651 暂无评论 # 第1章 预备知识 ## 1.1 C++简介 C++融合了3种不同的编程方式:C语言代表的过程性语言、C++在C语言基础上添加的类代表的面向对象语言、C++模版支持的泛型编程。 ## 1.2. C++简史 ### C语言和C++的区别: - C语言是面向过程的编程语言,它强调编程的算法方面,具有使用结构化编程的特性; - C语言的设计原则是自顶向下,即将大型程序分解成小型、便于管理的任务; - C++是面向对象(OOP)的编程语言,它强调编程的数据方面,其理念是设计与问题的本质特性相对应的数据格式,并用类来描述这种新型数据格式,对象是根据这种规范构造的特定数据结构。通常,类规定了使用哪些数据来表示对象(数据)以及可以对这些数据执行哪些操作(方法); - 从低级组织(如类)到高级组织(如程序)的处理过程叫做自下向上的编程。 泛型编程:强调独立于特定数据类型,使用一个泛型函数处理不同数据类型的同一任务。 ## 1.3. 可移植性和标准 可移植性的两个障碍: 1. 硬件:硬件的特定程序是不可移植的(将依赖于硬件的部分放在函数模块中可以最大限度地降低可移植性问题,这样只需要重新编写这些模块即可); 2. 语言上的差异:不同计算机语言(XP、Linux)的语言习惯,为了统一语言工作方式,C++98/C++2003、C++11等标准应运而生。 ## 1.4. 程序创建的技巧 具体的步骤大体如下:编写源代码--编译源代码,生成目标代码--链接目标代码与其他代码(包括一些标准的启动代码),生成可执行代码 ### 常见的编译器及简单用法: - UNIX:cfront(已于1993停更),GNU g++。 CC xx.C(会删除过程中的xx.o,默认生成a.out); CC xx1.C xx2.C(会保留过程中的xx1.o、xx2.o,便于后续修改再编译,如CC xx1.C xx2.o); - Linux:g++。 g++ xx.cxx(会删除过程中的xx.o,默认生成a.out); g++ xx1.cxx xx2.cxx(会保留过程中的xx1.o、xx2.o,便于后续修改再编译,如CC xx1.C xx2.o); - Windows命令行:Cygwin,MinGW。 g++ xx.cpp(会删除过程中的xx.o,默认生成a.exe); - Windows编译器:Microsoft Visual C++。 Compile, Build, Make, Build All, Link, Execute, Run, Debug。 - 阅读全文 -