C 语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C 语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了 OOP(objectoriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
1982年,Bjarne Stroustrup 博士在 C 语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为 C++ 。因此:C++ 是基于C语言而产生的,它既可以进行 C 语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。
C语言与 C++ 的区别和联系:C语言是面向过程的语言,而 C++ 是面向对象的语言。从语法上讲,C语言是 C++ 的一部分,C语言代码几乎不用修改就能够用 C++ 的方式编译,简单说就是C++ 兼容 C语言。
1.2 C++ 发展史
1979年,贝尔实验室的本贾尼等人试图分析unix内核的时候,试图将内核模块化,于是在 C 语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为 C with classes。
//namespace 后加命名空间的名字,例如我将它命名为 fengye
namespace fengye
{
//注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
//命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int a, int b)
{
return a + b;
}
struct Node
{
struct Node* next;
int val;
};
(2)命名空间可以嵌套
namespace fengye1
{
int a;
int b;
int Add(int a, int b)
{
return a + b;
}
namespace fengye2
{
int c;
int d;
int Sub(int c, int d)
{
return c - d;
}
}
}
//Test.h
namespace fengye
{
int scanf = 1;
int fun(int a, int b)
{
return a * b;
}
}
//Test.cpp
namespace fengye
{
int rand = 10;
int Add(int a, int b)
{
return a + b;
}
struct Node
{
struct Node* next;
int val;
};
}
3.3.2 命名空间的使用
(1)加命名空间名称及作用域限定
符号 “:: ”在 C++ 中叫做作用域限定符,通过“命名空间名称::命名空间成员”便可以访问到命名空间中相应的成员。
using 是 C++ 中的一个关键字,该关键字的作用是展开命名空间。代码中的 using fengye::rand 指的是把 rand 单独展开在全局域中,展开之后的 rand 就相当于一个没有被封装的全局变量,可以任何调用。
ps:
#include <stdio.h>
#include <stdlib.h>
namespace fengye
{
int a = 10;
}
using fengye::rand;
int main()
{
printf("%d\n", a);
return 0;
}
运行结果:
但是如果展开的是一个已经定义有的函数,会造成重定义。因为展开之后的 rand 就相当于一个没有被封装的全局变量,相当于定义了 int rand = 10,就会造成与库里的函数名字相冲突,就会造成重定义。
ps:
(3)使用using namespace 命名空间名称引入
using namespace + 命名空间的名字 (ps:using namespace fengye),相当于将命名空间 fengye 利的变量全部展开到全局域中,这样域中的变量可以直接调用,变量前面不用加 fengye::
ps:
#include <stdio.h>
namespace fengye
{
int a = 10;
int b = 20;
int c = 30;
}
using namespace fengye;
int main()
{
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
运行结果:
注意:第三种方法虽然方便,但不推荐使用,日常练习中可以使用,在大型项目上推荐使用前两种方法。
using namespace std
std 是C++标准库的命名空间名,C++ 将标准库的定义实现都放到这个命名空间中.
using namespace std 把库里的所有东西全部展开到全局域了, 这样自己定义的东西可能就会与库中的造成冲突,所以工程项目中是不推荐使用这种方式的,日常练习可以使用,比较方便。
项目中推荐展开常用的命名空间名。
3.3.3 使用命名空间的一些建议
项目中,尽量不要 using namespace std;
日常练习用 using namespace std;
using namespace std 展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。
四、C++ 输入&输出
===========
ps:
#include<iostream>
using namespace std;
int main()
{
cout << "Hello world!!!" << endl;
return 0;
}
#include<iostream>
int main()
{
int a = 10;
int& ra;//错误
return 0;
}
运行结果:
7.2.2一个变量可以有多个引用
ps:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& ra = a;
int& rb = a;
cout << &a << endl;//取地址
cout << &ra << endl;
cout << &rb << endl;
return 0;
}
运行结果:
7.2.3引用一旦引用一个实体,再不能引用其他实体
ps:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& ra = a;
int b = 20;
ra = b;// ra 是 b 的别名呢?还是 b 赋值给 ra 呢?答案是 b 赋值给 ra
cout << a << endl;
cout << ra << endl;
return 0;
}
运行结果:
结果说明 b 赋值给了 ra ,又因为 ra 是 a 的引用,所以 a 的值被改成了 20
7.3 常引用
定义:被 const 修饰的引用是常引用。常引用会涉及到权限的问题。
ps:
//权限不能放大
const int a = 10;
//int& ra = a;//error
const int& ra = a;//true
//权限可以缩小
int c = 10;
const int& rc = c;//true
//权限相同
const int d = 10;
const int& rd = d;
权限可以缩小和不变,但是权限不能扩大。正常的变量的权限可以进行读写,用 const 修饰的变量变成了常变量,只有读的权限,写的权限被限制了,说明用 const 修饰的变量权限缩小了。ps:const int a = 10,被 const 修饰权限缩小了,然后进行 int& ra = a,这明显错了,权限不能放大; a 下面的道理相同,就不解释了。
ps:
double e = 12.34;
int f = e;//发生整型提升
//int& re = e; // 该语句编译时会出错,类型不同,本质是权限放大了
const int& re = e;//true
将浮点型变量 e 赋值给整型变量 f 时会发生隐式类型转换,中间会产生一个临时变量,这个临时变量具有常性,跟常变量的属性一致。ps:int& re = e,e 产生的临时变量具有常性,只有读权限,权限缩小了;而 re 具有读写权限,这样一来临时变量转换成int& re 后,临时变量的权限被放大了,所以 error。而 const 修饰的引用,权限变小了,与临时变量的权限一致,可以转换。
这也说明,用 const 修饰的引用可以保护实参不被改变。
本人能力有限,已经尽最大努力解释了。•᷄ࡇ•᷅
7.4 引用使用场景
7.4.1 引用做参数
ps:
#include<iostream>
using namespace std;
void Swap(int& a1, int& a2)
{
int temp = a1;
a1 = a2;
a2 = temp;
}
int main()
{
int a = 1, b = 2;
Swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间;指针开辟了4 or 8 byte 的空间
ps:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& ra = a;
cout << "&a = " << &a << endl;
cout << "&ra = " << &ra << endl;
return 0;
}
运行结果:
在底层实现上,引用是按照指针方式来实现的。
ps:
#include<iostream>
using namespace std;
int main()
{
//从语法角度,ra没有开辟空间
int a = 10;
int& ra = a;
ra = 20;
//从语法角度,pa 开了4 or 8 byte
int* pa = &a;
*pa = 20;
return 0;
}
#include<iostream>
using namespace std;
int TestAuto()
{
return 10;
}
int main()
{
int a = 10;
auto b = a;//auto 自动推导类型
auto c = 'a';
auto d = TestAuto();
//typeid().name 的作用是输出变量的类型
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
return 0;
}
C 语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C 语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了 OOP(objectoriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
1982年,Bjarne Stroustrup 博士在 C 语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为 C++ 。因此:C++ 是基于C语言而产生的,它既可以进行 C 语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。
C语言与 C++ 的区别和联系:C语言是面向过程的语言,而 C++ 是面向对象的语言。从语法上讲,C语言是 C++ 的一部分,C语言代码几乎不用修改就能够用 C++ 的方式编译,简单说就是C++ 兼容 C语言。
1.2 C++ 发展史
1979年,贝尔实验室的本贾尼等人试图分析unix内核的时候,试图将内核模块化,于是在 C 语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为 C with classes。
//namespace 后加命名空间的名字,例如我将它命名为 fengye
namespace fengye
{
//注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
//命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int a, int b)
{
return a + b;
}
struct Node
{
struct Node* next;
int val;
};
(2)命名空间可以嵌套
namespace fengye1
{
int a;
int b;
int Add(int a, int b)
{
return a + b;
}
namespace fengye2
{
int c;
int d;
int Sub(int c, int d)
{
return c - d;
}
}
}
//Test.h
namespace fengye
{
int scanf = 1;
int fun(int a, int b)
{
return a * b;
}
}
//Test.cpp
namespace fengye
{
int rand = 10;
int Add(int a, int b)
{
return a + b;
}
struct Node
{
struct Node* next;
int val;
};
}
3.3.2 命名空间的使用
(1)加命名空间名称及作用域限定
符号 “:: ”在 C++ 中叫做作用域限定符,通过“命名空间名称::命名空间成员”便可以访问到命名空间中相应的成员。
using 是 C++ 中的一个关键字,该关键字的作用是展开命名空间。代码中的 using fengye::rand 指的是把 rand 单独展开在全局域中,展开之后的 rand 就相当于一个没有被封装的全局变量,可以任何调用。
ps:
#include <stdio.h>
#include <stdlib.h>
namespace fengye
{
int a = 10;
}
using fengye::rand;
int main()
{
printf("%d\n", a);
return 0;
}
运行结果:
但是如果展开的是一个已经定义有的函数,会造成重定义。因为展开之后的 rand 就相当于一个没有被封装的全局变量,相当于定义了 int rand = 10,就会造成与库里的函数名字相冲突,就会造成重定义。
ps:
(3)使用using namespace 命名空间名称引入
using namespace + 命名空间的名字 (ps:using namespace fengye),相当于将命名空间 fengye 利的变量全部展开到全局域中,这样域中的变量可以直接调用,变量前面不用加 fengye::
ps:
#include <stdio.h>
namespace fengye
{
int a = 10;
int b = 20;
int c = 30;
}
using namespace fengye;
int main()
{
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
运行结果:
注意:第三种方法虽然方便,但不推荐使用,日常练习中可以使用,在大型项目上推荐使用前两种方法。
using namespace std
std 是C++标准库的命名空间名,C++ 将标准库的定义实现都放到这个命名空间中.
using namespace std 把库里的所有东西全部展开到全局域了, 这样自己定义的东西可能就会与库中的造成冲突,所以工程项目中是不推荐使用这种方式的,日常练习可以使用,比较方便。
项目中推荐展开常用的命名空间名。
3.3.3 使用命名空间的一些建议
项目中,尽量不要 using namespace std;
日常练习用 using namespace std;
using namespace std 展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。
四、C++ 输入&输出
===========
ps:
#include<iostream>
using namespace std;
int main()
{
cout << "Hello world!!!" << endl;
return 0;
}
#include<iostream>
int main()
{
int a = 10;
int& ra;//错误
return 0;
}
运行结果:
7.2.2一个变量可以有多个引用
ps:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& ra = a;
int& rb = a;
cout << &a << endl;//取地址
cout << &ra << endl;
cout << &rb << endl;
return 0;
}
运行结果:
7.2.3引用一旦引用一个实体,再不能引用其他实体
ps:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& ra = a;
int b = 20;
ra = b;// ra 是 b 的别名呢?还是 b 赋值给 ra 呢?答案是 b 赋值给 ra
cout << a << endl;
cout << ra << endl;
return 0;
}
运行结果:
结果说明 b 赋值给了 ra ,又因为 ra 是 a 的引用,所以 a 的值被改成了 20
7.3 常引用
定义:被 const 修饰的引用是常引用。常引用会涉及到权限的问题。
ps:
//权限不能放大
const int a = 10;
//int& ra = a;//error
const int& ra = a;//true
//权限可以缩小
int c = 10;
const int& rc = c;//true
//权限相同
const int d = 10;
const int& rd = d;
权限可以缩小和不变,但是权限不能扩大。正常的变量的权限可以进行读写,用 const 修饰的变量变成了常变量,只有读的权限,写的权限被限制了,说明用 const 修饰的变量权限缩小了。ps:const int a = 10,被 const 修饰权限缩小了,然后进行 int& ra = a,这明显错了,权限不能放大; a 下面的道理相同,就不解释了。
ps:
double e = 12.34;
int f = e;//发生整型提升
//int& re = e; // 该语句编译时会出错,类型不同,本质是权限放大了
const int& re = e;//true
将浮点型变量 e 赋值给整型变量 f 时会发生隐式类型转换,中间会产生一个临时变量,这个临时变量具有常性,跟常变量的属性一致。ps:int& re = e,e 产生的临时变量具有常性,只有读权限,权限缩小了;而 re 具有读写权限,这样一来临时变量转换成int& re 后,临时变量的权限被放大了,所以 error。而 const 修饰的引用,权限变小了,与临时变量的权限一致,可以转换。
这也说明,用 const 修饰的引用可以保护实参不被改变。
本人能力有限,已经尽最大努力解释了。•᷄ࡇ•᷅
7.4 引用使用场景
7.4.1 引用做参数
ps:
#include<iostream>
using namespace std;
void Swap(int& a1, int& a2)
{
int temp = a1;
a1 = a2;
a2 = temp;
}
int main()
{
int a = 1, b = 2;
Swap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间;指针开辟了4 or 8 byte 的空间
ps:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& ra = a;
cout << "&a = " << &a << endl;
cout << "&ra = " << &ra << endl;
return 0;
}
运行结果:
在底层实现上,引用是按照指针方式来实现的。
ps:
#include<iostream>
using namespace std;
int main()
{
//从语法角度,ra没有开辟空间
int a = 10;
int& ra = a;
ra = 20;
//从语法角度,pa 开了4 or 8 byte
int* pa = &a;
*pa = 20;
return 0;
}
#include<iostream>
using namespace std;
int TestAuto()
{
return 10;
}
int main()
{
int a = 10;
auto b = a;//auto 自动推导类型
auto c = 'a';
auto d = TestAuto();
//typeid().name 的作用是输出变量的类型
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
return 0;
}