目录
一、C++和C的区别
面向过程语言:C ----->重视求解过程
面向对象语言:C++ ------>重视求解的方法
C++在C的基础上引入了更多的元素,例如类,类的私密性要比C中的结构体更加优秀,引用,重载,命名空间,以及STL库,模板编程和更多的函数,在面向对象的编程上更加高效。C语言的优势则是更加底层,编译速度会更快,在编写内核时大多数都是C语言去写。
在C++中,命名空间(Namespace)是一种组织代码的方式,主要用于解决全局变量、函数或类的命名冲突问题。命名空间提供了一种封装机制,允许开发者将相关的类、函数、变量等放在一个逻辑上封闭的区域中,这样相同的名字在不同的命名空间中可以共存,而不会相互干扰。
二、命名空间
用于解决命名冲突/明明污染问题
【1】接触到的第一个命名空间
标准命名空间std:cout endl cin
如果代码中没有using namespace std,cout和endl会报错
【2】定义
命名空间中可以存放,标识符:变量名、函数名、结构体名、枚举名
namespace 命名空间名
{
定义变量;
函数声明;
结构体名;
···
};
命名空间中,只能存放函数的声明,不能放函数的定义
【3】使用命名空间中的标识符
域限定符 ::
i)全局导入整体命名空间
using namespce 命名空间名;
在该行下的所有代码,都可以使用A中的所有标识符
ii)全局导入部分标识符
using 命名空间名::标识符名;
using A::a; ---->后面的代码都可以使用命名空间A中的标识符a
在该行下的所有代码,可以使用导入的指定的标识符
iii)局部导入标识符
在哪个位置使用,使用时直接通过域标识符来进行限定
include <iostream>
using namespace std;
namespace A
{
int a=90;
char c='x';
float p=3.14;
void fun();
};
int main()
{
A::fun();
cout << A::a << endl;
return 0;
}
include <iostream>
using namespace std;
namespace A
{
int a=90;
char c='x';
float p=3.14;
void fun();
};
//命名空间内声明fun函数,在命名空间外定义fun函数,需要给函数名加域限定符::
void A::fun()
{
cout << "fun函数" << endl;
}
//全局导入命名空间中的所有标识符
//using namespace A;
//全局导入命名空间中的部分标识符
/*using A::fun;
using A::a;
*/
int main()
{
A::fun();
cout << A::a << endl;
return 0;
}
【4】命名冲突问题*
main.cpp:27:5: error: call to 'fun' is ambiguous
main.cpp:8:10: note: candidate function
main.cpp:12:6: note: candidate function
i)两个命名空间中标识符冲突
- 两个命名空间中有同名成员
- 同时可以访问两个命名空间中的成员
怎么解决:
- 命名空间名+域限定符
- 只导入一个命名空间,代码就只能访问导入的命名空间中的标识符
ii)局部变量和命名空间中标识符冲突
代码不会报错,但是只能默认访问局部变量
想要访问命名空间中的标识符:命名空间名+域限定符
namespace A
{
int a=90;
char c='x';
float p=3.14;
void fun();
};
int main()
{
//在使用的位置使用域限定符
A::fun();
int a=100;
cout << A::a << endl;
cout << "B中的a=" << B::a << endl;
return 0;
}
iii)全局变量和命名空间标识符冲突
访问全局变量:只在标识符前加域限定符 ::a ----->访问全局变量a
访问命名空间中标识符:命名空间名+域限定符
include <iostream>
using namespace std;
int a=1000; //定义了一个全局变量a
namespace A
{
int a=90;
char c='x';
float p=3.14;
void fun();
};
int main()
{
//在使用的位置使用域限定符
A::fun();
cout << ::a << endl; //加上域限定符访问全局变量的a,
//因为全局变量,默认在匿名空间中
cout << "B中的a=" << B::a << endl;
return 0;
}
【5】匿名空间
没有名字的命名空间,就是匿名空间
匿名空间中的标识符的访问方式:
::标识符名
注意:匿名空间中的标识符尽量不要和全局变量冲突
include <iostream>
using namespace std;
int a=1000; //定义了一个全局变量a
namespace B
{
int a=130;
}
//命名空间内声明fun函数,在命名空间外定义fun函数,需要给函数名加域限定符::
void A::fun()
{
cout << "fun函数" << endl;
}
//全局导入命名空间中的所有标识符
using namespace A;
//using namespace B;
//匿名空间,尽量不要使用匿名空间
namespace {
int a = 2000;
char c;
}
int main()
{
//在使用的位置使用域限定符
A::fun();
cout << ::a << endl; //加上域限定符访问全局变量的a,
//因为全局变量,默认在匿名空间中
cout << "B中的a=" << B::a << endl;
return 0;
}
【6】嵌套的命名空间
一个命名空间定义在另一个命名空间内
访问时需要逐层查找
include <iostream>
using namespace std;
namespace A1 {
int num1 = 10;
int num2 = 30;
namespace A2
{
int num1=1;
int num2=90;
int x = 7;
}
}
using namespace A1;
using namespace A1::A2;
int main()
{
//想要访问A2中的num1
//由于A2是包含在A1内的,想要访问到A2需要一层一层访问
cout << A1::A2::num1 << endl;
//cout << num2 << endl; 一定构成命名冲突问题
cout << A1::num2 << endl;
return 0;
}
【7】给命名空间重命名
namespace 新的名字 = 旧的名字;
include <iostream>
using namespace std;
namespace A1 {
int num1 = 10;
int num2 = 30;
namespace A2
{
int num1=1;
int num2=90;
int x = 7;
}
}
using namespace A1;
using namespace A1::A2;
int main()
{
//想要访问A2中的num1
//由于A2是包含在A1内的,想要访问到A2需要一层一层访问
cout << A1::A2::num1 << endl;
//cout << num2 << endl; 一定构成命名冲突问题
cout << A1::num2 << endl;
return 0;
}
【8】using的另一种用法
using还可以用于类型重定义
C++ 11标准才能使用using实现重定义
typedef int arr[5];<===>arr相当于int [5]
typedef int p; <===>p后面就相当于int
include <iostream>
using namespace std;
namespace p = A1; //把命名空间A1重命名为p,后面既可以使用A1访问也可以使用p访问
using namespace A1;
using namespace A1::A2;
int main()
{
//使用suing把int,重命名为INT,后面使用哪一个都可以定义整形变量
using INT = int;
INT a = 90;
cout << a << endl;
cout << sizeof(a) << endl;
return 0;
}