1.C++的由来
C++是1979年由贝尔实验室设计开发的,最初被命名为带类的C。
C++是一种静态类型、编译式、通用的、大小写敏感、不规则的编程语言。
C++被认为是一种中级语言,综合了高级语言和低级语言的特点、
C++是C的超集,任何合法的C程序都是合法的C++程序。
使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查。
C++支持面向对象的程序设计,包括面向对象开发的四大特性(封装、抽象、继承、多态)。
大部分的编译器支持ANSI C标准,即美国国家标准学会C标准(American National Standards Insititude,ANSI/ISO 9899)。
C++是C的超集,所以如果你熟悉C语言就很快能熟悉C++的语法。
C++也是符合面向对象设计范式的语言,所以如果你熟悉任何一种面向对象语言就不需要对C++的面向对象有任何担心。
C++代码需要经过编译器的编译、优化和代码生成阶段,生成特定平台上的机器码,然后才能在目标CPU上直接执行。这种过程是实现C++的跨平台性的关键,允许相同的源代码在不同的平台上编译和运行。
需要注意是的是C++的跨平台性仅体现于代码层面,不同平台的基础库的实现也不完全相同。
2.一个例程了解C++基础
以下是通过一个C++程序来熟悉C++的基础知识。当然你也可以在编译器中编译运行它。
1//预处理指令,比如 #include、#define、#if、#else、#line
2//条件
3
4//| <iostream> | 该文件定义了 * *cin、cout、cerr * *和 * *clog * *对象,分别对应于标准输入流、标准输出流、非缓冲标准错误流和缓冲标准错误流。 |
5//| <iomanip> | 该文件通过所谓的参数化的流操纵器(比如 * *setw * *和 * *setprecision * *),来声明对执行标准化 I / O 有用的服务。 |
6//| <fstream> | 该文件为用户控制的文件处理声明服务。我们将在文件和流的相关章节讨论它的细节。 |
7#include <iostream>
8#include <cstring>
9using namespace std;
10//专门用于解决上面的问题,它可作为附加信息来区分不同库中相同名称的函数、类、变量等。
11//使用了命名空间即定义了上下文。本质上,命名空间就是定义了一个范围。
12//using 指令也可以用来指定命名空间中的特定项目。
13using std::cout;
14
15//命名空间可以嵌套,您可以在一个命名空间中定义另一个命名空间
16namespace namespace_name1 {
17 // 代码声明
18 namespace namespace_name2 {
19 // 代码声明
20 }
21}
22
23#define MIN(a,b) (a<b ? a : b) //宏函数
24
25#define WIDTH 5 //预处理定义常量
26const int LENGTH = 10; //const声明指定类型常量
27//const类型在程序执行期间不能被修改改变
28//volatile告诉编译器,变量的值可能以程序未明确指定的方式被改变
29//由 restrict修饰的指针是唯一一种访问它所指向的对象的方式。只有 C99 增加了新的类型限定符 restrict
30
31int a, b; //变量可以在头部声明,但在主函数中进行定义和初始化
32
33
34//存储类
35//- auto (C++11中不再是C++存储类说明) //声明变量时根据初始化表达式自动推断该变量的类型
36//- register (C++11已弃用) //存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 '&' 运算符(因为它没有内存位置)。
37//- static //在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。
38//- extern //用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。
39//- mutable //仅适用于类的对象,它允许对象的成员替代常量。也就是说,mutable 成员可以通过 const 成员函数修改。
40//- thread_local (C++11) //声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。
41
42
43//运算符
44//+
45//-
46//*
47///
48//% 取模
49//++
50//--
51
52//关系运算符
53//==
54//!=
55//>
56//<
57//>=
58//<=
59
60//逻辑运算符
61//&& 与
62//|| 或
63//! 非
64
65
66//位运算符
67//& 位与
68//| 位或
69//^ 位异或
70//~ 补码
71//<< 左移
72//>> 右移
73
74//赋值运算符
75// =
76// +=
77// -=
78// *=
79// /=
80// %=
81// <<=
82// >>=
83// &=
84// |=
85
86//杂项运算符
87//sizeof 返回变量大小
88//Condition?X:Y //如果Condition?为真,则值为X:否则值为Y.
89//, 会顺序执行一系列运算。整个逗号表达式的值是逗号分割的列表中最后一个表达式的值
90//.(和)->(箭头) 用于引用类、结构和共用体的成员。
91//Cast 把一种数据类型转换为另一种数据类型。
92//& 返回变量的地址。
93//* 指向一个变量。
94
95//C++运算符存在优先级
96
97//循环类型
98//while循环
99//for循环 for的三个语句都不是必须的
100//do...while循环
101
102//循环控制语句
103//break;
104//continue;
105//goto (尽量不要使用)
106
107//判断
108//if
109//if..else
110//switch
111
112//形式参数
113//形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。
114
115//[传值调用] 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。
116//[指针调用] 该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
117//[引用调用] 该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
118//默认情况下 C++使用[传值调用]
119
120
121//C++支持默认参数
122int sum(int a, int b = 20) {
123 int result;
124 result = a + b;
125 return (result);
126}
127
128//Lambda表达式
129//C++11 支持匿名函数,称为Lambda函数
130//[](int x, int y) { return x < y; }
131
132
133//数学运算
134//cos sin tan log
135//pow x 的 y 次方
136//hypot 返回两个参数的平方总和的平方根
137//sqrt 参数的平方根
138//abs 整数绝对值
139//fabs 十进制数的绝对值
140//floor 返回小于或等于的最大整数
141
142
143
144int main()
145{
146
147 //<<运算符用于向屏幕传递多个值
148 //endl表示在末尾插入换行符,等同于"\n"
149
150 //输出各类型的字节大小
151 cout << "Size of char : " << sizeof(char) << endl;
152 cout << "Size of int : " << sizeof(int) << endl;
153 cout << "Size of short int : " << sizeof(short int) << endl;
154 cout << "Size of long int : " << sizeof(long int) << endl;
155 cout << "Size of float : " << sizeof(float) << endl;
156 cout << "Size of double : " << sizeof(double) << endl;
157 cout << "Size of wchar_t : " << sizeof(wchar_t) << endl;
158
159 //Size of char : 1
160 // Size of int : 4
161 // Size of short int : 2
162 // Size of long int : 4
163 // Size of float : 4
164 // Size of double : 8
165 // Size of wchar_t : 2
166 //基本内置类型
167//一个字节:char 、unsigned char、signed char
168//两个字节:short int、unsigned short int、signed short int
169//四个字节:int、 unsigned int、signed int、float、long int、signed long int、unsigned long int
170//八个字节:double、long double
171
172//变量的字节大小在不同编译器或平台上有所不同,long double至少与double一样大,但也有可能更大。
173
174//修饰符类型
175 //signed
176 //unsigned
177 // long
178 // short
179
180
181 typedef int feet; //将int类型取别名为feet
182 feet distance=1;
183 feet distance1;
184 distance1 = 2;
185 std::cout << "distance:" << distance << "\n";
186 std::cout << "distance1:" << distance1 << "\n";
187 //变量可以在声明的时候被初始化(指定一个初始值)
188 //不带初始化的定义:带有静态存储持续时间的变量会被隐式初始化为 NULL(所有字节的值都是 0),
189 //其他所有变量的初始值是未定义的。
190 //未初始化的值会导致编译不通过
191
192 //头部定义的变量会被默认初始化
193 //当局部变量被定义时,系统不会对其初始化,您必须自行对其初始化。定义全局变量时,系统会自动初始化为下列值:
194 // | int | 0
195 // | char | '\0'
196 // | float | 0
197 // | double | 0
198 // | pointer | NULL
199
200 std::cout << "a:" << a<< "\n";
201 std::cout << "b:" << b << "\n";
202 a = 1;
203 b = 2;//初始化头部声明的变量
204
205 std::cout << "WIDTH:" << WIDTH << "\n";
206 std::cout << "LENGTH:" << LENGTH << "\n";
207 //WIDTH = 10; //预处理定义的常量无法被赋值 //会提示无法被修改的左值
208 //LENGTH = 10;//预处理定义的常量无法被赋值 //会提示无法被修改的左值
209
210
211 //整数常量
212 85; //十进制
213 0213;//八进制
214 0x4b;//16进制
215 30u;//无符号整数
216 30l;//长整数
217 30ul;//无符号长整数
218 std::cout << "八进制:" << 0213 << "\n";
219 //显示139
220
221 //浮点数常量
222 3.14159;
223 3.14158E-5L;
224
225 //字符常量
226 'c'; //char类型
227 L'x'; //wchar_t类型
228 //转义字符
229 '\\'; //"\"
230 '\''; //"'"
231 '\?'; //"?"
232 '\a'; //"警报铃声"
233 '\b'; //"退格"
234 '\f'; //"换页"
235 '\n'; //"换行"
236 '\r'; //"回车"
237 '\t'; //"水平制表符"
238 '\v'; //"垂直制表符"
239 '\ooo'; //"一到三位的八进制数"
240 //'\xhh...'; //"\"
241
242 //字符串常量
243 "abafdfsdfsd";
244
245
246
247
248
249
250 //定义枚举类型
251 enum color { red, green=5, blue } c;
252 c = blue;
253 //这里blue的值会为6
254 std::cout<<"blue:"<<c << "\n";
255
256
257 //数组
258 double array[10]; //一维数组
259 double array1[5] = { 1000.0, 2.0, 3.4, 17.0, 50.0 };
260 double array2[] = { 1000.0, 2.0, 3.4, 17.0, 50.0 };
261//多维数组 | C++ 支持多维数组。多维数组最简单的形式是二维数组。
262//指向数组的指针 | 您可以通过指定不带索引的数组名称来生成一个指向数组中第一个元素的指针。
263//传递数组给函数 | 您可以通过指定不带索引的数组名称来给函数传递一个指向数组的指针。
264//从函数返回数组 | C++ 允许从函数返回数组。
265
266//字符串操作
267// **strcpy(s1, s2); **复制字符串 s2 到字符串 s1。 |
268// **strcat(s1, s2); **连接字符串 s2 到字符串 s1 的末尾。 |
269// **strlen(s1); **返回字符串 s1 的长度。 |
270// **strcmp(s1, s2); **如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。 |
271//**strchr(s1, ch); **返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 |
272//**strstr(s1, s2); **返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。
273
274
275 //string类
276 // 复制 str1 到 str3
277 string str1 = "Hello";
278 string str2 = "World";
279 string str3;
280 int len;
281 str3 = str1;
282 cout << "str3 : " << str3 << endl;
283 // 连接 str1 和 str2
284 str3 = str1 + str2;
285 cout << "str1 + str2 : " << str3 << endl;
286
287 //**指针**是一个变量,其值为另一个变量的地址
288 //C++ Null 指针 | C++ 支持空指针。NULL 指针是一个定义在标准库中的值为零的常量。 |
289 // C++ 指针的算术运算 | 可以对指针进行四种算术运算:++、--、 + 、 - |
290 // C++ 指针 vs 数组 | 指针和数组之间有着密切的关系。 |
291 //C++ 指针数组 | 可以定义用来存储指针的数组。 |
292 //C++ 指向指针的指针 | C++ 允许指向指针的指针。 |
293 //C++ 传递指针给函数 | 通过引用或地址传递参数,使传递的参数在调用函数中被改变。 |
294 // C++ 从函数返回指针 | C++ 允许函数返回指针到局部变量、静态变量和动态内存分配。 |
295
296 //C++ //引用
297
298 //引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
299
300 //C++ 引用 vs 指针
301
302 //引用很容易与指针混淆,它们之间有三个主要的不同:
303
304 //不存在空引用。引用必须连接到一块合法的内存。
305 //一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
306 //引用必须在创建时被初始化。指针可以在任何时间被初始化。
307 // 声明简单的变量
308 int i;
309 double d;
310
311 // 声明引用变量
312 int& r = i;
313 double& s = d;
314
315 //cout 标准输出流
316 //cin 标准输入流
317 //cerr 标准错误流
318 //clog 标准日志流
319 std::cout << "Hello World!\n";
320 std::cin.get();//等待输入
321 //标准错误流
322 char str_err[] = "Unable to read....";
323 cerr << "Error message : " << str_err << endl;
324 clog << "Error message : " << str_err << endl;
325
326 //结构体
327 struct Books {
328 char title[50];
329 char author[50];
330 char subject[100];
331 int book_id; } book;
332 strcpy_s(book.title, "C++ 教程");
333 struct Books* struct_pointer; //定义指向结构体的指针
334 struct_pointer = &book; //指针赋值
335 struct_pointer->title; //使用该指针访问结构体成员
336 cout << struct_pointer->title << endl;
337 //使用typeedef定义结构体
338 typedef struct {
339 char title[50];
340 char author[50];
341 char subject[100];
342 int book_id;
343 }Books1;
344 return 0;
345
346
347
348}
349
350
351//C++ 的封装、抽象、继承、多态
352//C++ 的重载 在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。
353//多态 当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
354//C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
355
356//虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。
357//我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
358
359//数据抽象是一种依赖于接口和实现分离的编程(设计)技术。
360//C++ 类为** 数据抽象** 提供了可能。它们向外界提供了大量用于操作对象数据的公共方法,也就是说,外界实际上并不清楚类的内部实现。
361//使用公共标签定义的成员都可以访问该程序的所有部分。一个类型的数据抽象视图是由它的公共成员来定义的。
362//使用私有标签定义的成员无法访问到使用类的代码。私有部分对使用类型的代码隐藏了实现细节。
363//** 数据封装** 是一种把数据和操作数据的函数捆绑在一起的机制,** 数据抽象** 是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
364
365
366//异常捕获
367//try catch throw
368//catch可以有多个来捕获不同类型的异常
369//** std::exception** | 该异常是所有标准 C++ 异常的父类。
370//... 可捕获任何类型的异常
371
372
373//动态内存
374//** 栈:** 在函数内部声明的所有变量都将占用栈内存。
375//- **堆: * *这是程序中未使用的内存,在程序运行时可用于动态分配内存。
376//在 C++ 中,您可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址。这种运算符即** new** 运算符。
377//如果您不需要动态分配内存,可以使用** delete** 运算符,删除之前由 new 运算符分配的内存。
378
379//** malloc()** 函数在 C 语言中就出现了,在 C++ 中仍然存在,但建议尽量不要使用 malloc() 函数。
380//new 与 malloc() 函数相比,其主要的优点是,new 不只是分配了内存,它还创建了对象。
381
382//构造函数与析构函数
383class Box {
384public:
385 Box() {
386 cout << "调用构造函数!" << endl;
387 }
388 ~Box() {
389 cout << "调用析构函数!" << endl;
390 }
391};
392
393//函数模板 返回a、b中的最大值
394template <typename T>inline T const& Max(T const& a, T const& b) {
395 return a < b ? b : a;
396}
……