【C++ 语言】命名空间 ( namespace | 命名空间定义 | 命名空间嵌套 | 域作用符 | 与 include 对比 )(二)

简介: 【C++ 语言】命名空间 ( namespace | 命名空间定义 | 命名空间嵌套 | 域作用符 | 与 include 对比 )(二)

7.声明内层命名空间的访问方式 : 如果内层的命名空间被声明 , 那么可以不使用域作用符 , 直接访问内层命名空间中的方法 ;

//声明内层命名空间 : 如果声明了 内层的命名空间 , 可以调用内层命名空间中定义的 say_hi_inner() 方法
  say_hi_inner();


8.嵌套命名空间代码示例 : ① 命名空间定义 , ② 命名空间声明 , ③ 命名空间调用 ;


//命名空间定义 : 自定义命名空间
namespace mynamespace {
  //调用时 需要调用 mynamespace::say_hi() 方法进行调用
  void say_hi() {
  //注意 : 下面的 cout 和 endl 定义在 std 命名空间中
  //如果没有声明 using namespace std; , 就必须使用域作用符号 "::" 才能访问
  //域作用符格式 : 命名空间::调用内容
  std::cout << "自定义命名空间 mynamespace say_hi() 方法 : Hi!" << std::endl;
  }
  //嵌套的命名空间需要调用 mynamespace::myinnernamespace::say_hi() 才能调用该方法
  namespace myinnernamespace {
  void say_hi_inner() {
    //注意 : 下面的 cout 和 endl 定义在 std 命名空间中
    //如果没有声明 using namespace std; , 就必须使用域作用符号 "::" 才能访问
    //域作用符格式 : 命名空间::调用内容
    std::cout << "自定义嵌套的命名空间 myinnernamespace say_hi_inner() 方法 : Hi Inner!" << std::endl;
  }
  }
}
//声明自定义的命名空间 , 声明 外层命名空间 , 
//可以直接调用 say_hi() 方法 ; 
//调用内层的 say_hi_inner() 方法需要使用 myinnernamespace::say_hi_inner() 进行调用
using namespace mynamespace;
//声明内层的命名空间 , 需要使用 外层命名空间::内层命名空间 进行声明
//这样就可以直接调用内层命名空间的 say_hi_inner() 方法了
using namespace mynamespace::myinnernamespace;
//下面是方法中的代码
  //没有声明命名空间 : 嵌套的命名空间调用 , 需要使用两个域作用符访问最内层命名空间中定义的方法 
  mynamespace::myinnernamespace::say_hi_inner(); 
  //只声明了外层命名空间 , 这里就可以省略上面的外层命名空间 , 
  //但是内层的命名空间不能省略 , 因为没有声明内部命名空间, 
  //需要一个域作用符访问内层命名空间中的方法
  myinnernamespace::say_hi_inner();
  //声明内层命名空间 : 如果声明了 内层的命名空间 , 可以调用内层命名空间中定义的 say_hi_inner() 方法
  say_hi_inner();


9.执行结果 :

自定义嵌套的命名空间 myinnernamespace say_hi_inner() 方法 : Hi Inner!
自定义嵌套的命名空间 myinnernamespace say_hi_inner() 方法 : Hi Inner!
自定义嵌套的命名空间 myinnernamespace say_hi_inner() 方法 : Hi Inner!


image.png

image.png




域作用符


域作用符 :


1.域作用符的作用 : 主要有两个作用 ;

① 访问命名空间 : 一个是访问命名空间中的变量和方法 ;

② 访问类成员 : 另一个是调用类中的方法 或 成员变量 ;

上述访问命名空间中的方法已经展示过了 , 下面介绍下访问类成员变量 ;


2.定义类中的成员变量 : 该变量定义在类中 ;

//类的成员变量
int a_int = 888;


3.在方法中定义一个同名的成员变量 : 注意类中的成员变量与方法中的局部变量赋值不同 , 用于区分两个变量 ;

//方法中的局部变量
  int a_int = 999;


4.使用域作用符访问类成员变量 : 访问类中的变量格式为 “::变量名” , 如 ::a_int ;

//域作用符 :: 作用
  //① 调用命名空间中的方法 或 变量
  //② 调用类中的方法 或 成员变量 , ::变量名称 可以访问类中的成员变量
  //方法中的局部变量
  int a_int = 999;
  //域作用符作用
  std::cout << "类中的成员变量 ::a_int : " << ::a_int << " 方法中的局部变量 a_int : " << a_int << std::endl;


5.代码示例 :

//类的成员变量
int a_int = 888;
//下面是方法中的代码
  //域作用符 :: 作用
  //① 调用命名空间中的方法 或 变量
  //② 调用类中的方法 或 成员变量 , ::变量名称 可以访问类中的成员变量
  //方法中的局部变量
  int a_int = 999;
  //域作用符作用
  std::cout << "类中的成员变量 ::a_int : " << ::a_int << " 方法中的局部变量 a_int : " << a_int << std::endl;




6.执行结果 :

类中的成员变量 ::a_int : 888 方法中的局部变量 a_int : 999

image.png





命名空间 与 include 区别


在 C++ 代码中 , 经常遇到 #include "c_extern.h" 和 using namespace std; 代码 , 两种方式都可以声明可使用的若干变量和方法 ;


include 作用 : 将包含的文件 在编译时 拷贝到 这个文件中 , 如上面 #include "c_extern.h" , 在编译时就将 c_extern.h 头文件中的内容 , 全部拷贝到本文件中 使用 #include "c_extern.h" 的位置 ;

命名空间的作用 : 表明后面所有的代码都使用这个命名空间 , 如果调用命名空间中的方法, 就会去对应的命名空间中查找对应方法;

函数完全重复的情况 : 如果出现两个函数 , 其 ① 函数名 ② 参数个数 ③ 参数顺序 ④ 返回值 完全重复 , 这样就会造成冲突 ;

命名空间作用 : 命名空间就是避免出现上述函数完全重复的情况 , 可以将重复的函数定义在命名空间中 , 这样就能区分两个完全相同的函数 ;




命名空间定义与使用完整代码


代码中包含部分 C/C++ 兼容 , C/C++ 字符串 相关代码 , 属于上一篇博客遗留, 可忽略 , 只看命名空间相关的代码 ;


// 001_CMake_1.cpp: 定义应用程序的入口点。
//
#include "001_CMake_1.h"
#include "c_extern.h"
//命名空间定义 : 自定义命名空间
namespace mynamespace {
  //调用时 需要调用 mynamespace::say_hi() 方法进行调用
  void say_hi() {
  //注意 : 下面的 cout 和 endl 定义在 std 命名空间中
  //如果没有声明 using namespace std; , 就必须使用域作用符号 "::" 才能访问
  //域作用符格式 : 命名空间::调用内容
  std::cout << "自定义命名空间 mynamespace say_hi() 方法 : Hi!" << std::endl;
  }
  //嵌套的命名空间需要调用 mynamespace::myinnernamespace::say_hi() 才能调用该方法
  namespace myinnernamespace {
  void say_hi_inner() {
    //注意 : 下面的 cout 和 endl 定义在 std 命名空间中
    //如果没有声明 using namespace std; , 就必须使用域作用符号 "::" 才能访问
    //域作用符格式 : 命名空间::调用内容
    std::cout << "自定义嵌套的命名空间 myinnernamespace say_hi_inner() 方法 : Hi Inner!" << std::endl;
  }
  }
}
using namespace std;
//声明自定义的命名空间 , 声明 外层命名空间 , 
//可以直接调用 say_hi() 方法 ; 
//调用内层的 say_hi_inner() 方法需要使用 myinnernamespace::say_hi_inner() 进行调用
using namespace mynamespace;
//声明内层的命名空间 , 需要使用 外层命名空间::内层命名空间 进行声明
//这样就可以直接调用内层命名空间的 say_hi_inner() 方法了
using namespace mynamespace::myinnernamespace;
//类的成员变量
int a_int = 888;
//定义方法接收 int& 引用类型变量
//并在方法中修改该变量的值
void quote(int& b) {
  b = 888;
}
int main()
{
  cout << "Hello CMake。" << endl;
  //1. C C++ 兼容
  //博客地址 : https://hanshuliang.blog.csdn.net/article/details/98840708
  //调用 c_extern.h 头文件中定义的方法
  //该方法定义在了 C 语言文件中
  add(1, 2);
  //2. 引用数据类型
  //博客地址 : https://hanshuliang.blog.csdn.net/article/details/99239635
  //代码 展示 流程 : 
  //① 定义 普通 类型 变量
  int a = 8;
  //② 定义 引用类型变量, 格式 : 类型名称& 变量名 = 对应类型变量名称 ;
  int& b = a;
  //③ 调用函数传入引用类型参数 : 将引用类型传给接收引用类型的方法
  quote(b);
  //④ 打印引用数据类型的修改结果 , 结果是 b 被修改成了 888
  cout << b << endl;
  //引用数据类型定义与使用 : 
  // ① 引用数据类型定义 : 类型名称& 变量名 = 对应类型变量名称 ;
  // ② 引用数据类型的使用方法 : 直接当做原来的变量使用即可, 可以替换原来变量的位置使用
  //引用类型解析 : 
  // ① int& 是引用数据类型 , b 是 a 的引用 
  // ② 分配一块内存存放 int 类型数据 8 , 将该内存赋予一个别名 a
  // ③ 同时又给该内存赋予另外一个别名 b 
  //3. 字符串使用
  //C 字符串
  //博客地址 : https://hanshuliang.blog.csdn.net/article/details/99295034
  //C 字符串 表示方法 : 
  // ① 字符数组 : 本质是 字符 数组 char[] , 这里注意字符数组要以 NULL 或 '\0' 结尾; 
  char string_c[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
  // ② 指针 : 使用指针形式表示字符串 , 默认末尾增加 '\0' ;
  char* string_c_p = "hello";
  //字符串打印 : 
  // ① 打印字符串 , cout 后的 << 后可以打印 字符串 , 也可以打印变量
  // ② 输出 cout << 字符串或变量1 << 字符串或变量2 ... << endl 可以拼接 输出信息
  cout << "string_c : " << string_c << endl;
  cout << "string_c_p : " << string_c_p << endl;
  //C 语言中的字符串操作
  //拷贝字符串 
  char string_c_copy_destination[6];
  char string_c_copy_source[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
  // ① 参数 : strcpy 方法是拷贝字符串的方法 , 第一个参数是目标字符串 , 第二个参数是源字符串
  // ② 作用 : 该方法是将 源字符串 拷贝到 目标字符串中
  strcpy(string_c_copy_destination, string_c_copy_source);
  // ③ 打印拷贝结果 : 
  cout << "string_c_copy_destination : " << string_c_copy_destination << endl;
  //拼接字符串 
  //① 定义目标字符串 : 拼接字符串的目标字符串的大小一定要大于等于要拼接的两个字符串大小之和, 否则会报错
  char string_c_cat_destination[50] = " cat dst ";
  char string_c_cat_source[] = " cat src ";
  //② 拼接字符串方法参数 : 第一个参数是目标字符串 , 第二个参数是源字符串
  //③ 目标字符串大小 : 注意 目标字符串的 大小一定要大于 两个字符串实际大小
  strcat(string_c_cat_destination, string_c_cat_source);
  //④ 打印字符串拼接结果 : 
  cout << "string_c_cat_destination : " << string_c_cat_destination << endl;
  //获取字符串长度
  //① 参数 : 传入要获取的字符串 , 该长度不含 '\0' 结尾标志
  //② 作用 : 获取实际的字符串长度 , 即自动识别 '\0' 位置 , 获取其长度 , 与所占用的内存大小无关
  char string_c_len[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
  char string_c_len2[20] = { 'h', 'e', 'l', 'l', 'o', '\0' };
  char * string_c_len3 = "hello";
  //① 字符数组长度 , 测量从开始到 '\0' 的长度, 不包括 '\0'
  int len1 = strlen(string_c_len);
  //② 指定大小的字符数组长度 , 结果不是指定的大小的值 , 获取的是实际字符串长度
  int len2 = strlen(string_c_len2);
  //③ 指针表示的字符串 , 其获取的大小是实际字符串大小, 不包含自动添加的 '\0' 
  int len3 = strlen(string_c_len3);
  //④ 打印 三个字符串大小
  cout << "len1 : " << len1
  << " len2 : " << len2
  << " len3 : " << len3
  << endl;
  //字符串比较
  // ① 参数说明 : 参数是需要比较的两个字符串 , 第一个参数 str1 , 第二个参数 str2
  // ② 对比规则 : str1 和 str2 两个字符串 , 从左到右 逐个对比 ASCII 码 大小 ; 
  //  a. 如果 str1 等于 str2 , 返回 0; 
  //  b. 如果 str1 > str2 , 返回值 大于 0 ;
  //  c. 如果 str1 < str2 , 返回值 小于 0 ;
  //定义需要比较的字符串
  char* string_c_comp_1 = "Hello";
  char* string_c_comp_2 = "Hello";
  char* string_c_comp_3 = "hello";
  // ① 两个字符串相等
  int cmp_result_1_2 = strcmp(string_c_comp_1, string_c_comp_2);
  // ② "Hello" 字符串 (H 对应 ASCII 72) 小于 "hello" 字符串 (h 对应 ASCII 104) , 返回值 小于 0
  int cmp_result_1_3 = strcmp(string_c_comp_1, string_c_comp_3);
  // ③ "hello" 字符串 (h 对应 ASCII 104) 大于 "Hello" 字符串 (H 对应 ASCII 72) , 返回值 大于 0
  int cmp_result_3_1 = strcmp(string_c_comp_3, string_c_comp_1);
  //输出字符串对比结果
  cout << "cmp_result_1_2 : " << cmp_result_1_2 
  << " cmp_result_1_3 : " << cmp_result_1_3
  << " cmp_result_3_1 : " << cmp_result_3_1
  << endl;
  //C++ 字符串
  //博客地址 : https://hanshuliang.blog.csdn.net/article/details/99336346
  // C++ string 类 : 该类定义在 iostream 头文件中
  //创建 string 类型对象有三种方法 : 
  //① 直接使用字符串赋值 
  //② 调用构造方法赋值 
  //③ 最后可以调用 new 为字符串分配一块内存
  //① 使用字符串赋值
  string string_c_plus_1 = " Hello ";
  //② 调用构造方法 初始化字符串
  string string_c_plus_2(string_c_plus_1);
  string string_c_plus_3(" World ");
  //上面的三种字符串不需要释放 , 因为其定义在栈内存中 , 下面使用 new 创建字符串的情况需要 delete 释放内存 ; 
  //③ 使用 new 申请的内存 , 需要使用 delete 释放
  string *string_c_plus_4 = new string(" New ");
  delete string_c_plus_4;
  //使用 new [] 申请的数组 , 需要使用 delete[] 释放
  //使用 malloc 申请的内存 , 需要使用 free 释放
  //C++ 字符串输出
  //字符串对象不能直接在 cout 中输出, cout << string string_c_plus_5 << endl; 是错误的
  //cout << string_c_plus_2 << endl;
  //要将 string 对象打印到控制台上, 需要将其转为 C 字符串 , char* 或 char[] 才能输出
  cout << string_c_plus_1.c_str() << endl;
  //C++ 字符串拼接
  //① "+" : 操作符重载 , 重新定义了 加号运算符的行为 , 这里加号可以实现字符串拼接 , 与 Java 类似
  //② 调用 string 对象的 append 方法 , 拼接字符串
  string string_c_plus_5 = string_c_plus_1 + string_c_plus_3;
  string string_c_plus_6 = string_c_plus_1.append( string_c_plus_3 );
  //输出拼接的字符串
  cout << string_c_plus_5.c_str() << endl;
  cout << string_c_plus_6.c_str() << endl;
  //获取 C++ 字符串长度 : 调用 string 对象的 size() 方法 , 获取字符串长度
  int string_c_plus_1_size = string_c_plus_1.size();
  cout << "string_c_plus_1_size : " << string_c_plus_1_size << endl;
  //判断 C++ 字符串是否为空 : 调用 string 对象的 empty() 方法 ; 
  bool string_c_plus_1_empty = string_c_plus_1.empty();
  cout << "string_c_plus_1_empty : " << string_c_plus_1_empty << endl;
  //使用 new 创建的对象 , 就不能使用 . 访问其方法和变量 , 需要使用 -> 符号进行访问 
  // -> 相当于 (*). 运算, 先读取指针内容 , 然后访问其方法或变量
  string* string_c_plus_7 = new string(" New String ");
  //① 获取字符串长度 : 
  int string_c_plus_7_size = string_c_plus_7->size();
  cout << "string_c_plus_7 : " << string_c_plus_7_size << endl;
  //② 判断字符串是否为空 : 
  bool string_c_plus_7_empty = string_c_plus_7->empty();
  cout << "string_c_plus_7_empty : " << string_c_plus_7_empty << endl;
  //释放堆内存
  delete string_c_plus_7;
  //使用指针的好处 : 
  // ① 如果在栈内存中使用 , 有作用域限制 , 出了栈内存 作用域 , 该对象就无效了 ; 
  // ② 指针 大小为 4 ( 32 位系统 ) 或 8 ( 64 位系统 ) 个字节 , 
  //   其当做参数传递 比直接传递对象 ( 动辄几十上百字节甚至更高 ) 效率更高 
  //4. 命名空间
  //博客地址 : https://hanshuliang.blog.csdn.net/article/details/99406975
  // 命名空间 相当于 Java 中的 Package 包 , 
  //  上面的 cout endl string 等都定义在 std 命名空间中
  // 如果没有 using namespace std; 声明命名空间 , 
  //  那么必须使用域作用符 "::" ( 两个冒号 ) , 否则全都会报错
  std::cout << 
  "没有使用命名空间 需要使用 std::cout << ... << std::endl 打印" 
  << std::endl;
  //没有声明命名空间 : 调用自定义的 mynamespace 命名空间中的 say_hi 方法 , 必须使用域作用符
  mynamespace::say_hi();
  //声明命名空间 : 如果声明了 外层的命名空间 , 可以调用外层命名空间中定义的 say_hi() 方法
  say_hi();
  //没有声明命名空间 : 嵌套的命名空间调用 , 需要使用两个域作用符访问最内层命名空间中定义的方法 
  mynamespace::myinnernamespace::say_hi_inner(); 
  //只声明了外层命名空间 , 这里就可以省略上面的外层命名空间 , 
  //但是内层的命名空间不能省略 , 因为没有声明内部命名空间, 
  //需要一个域作用符访问内层命名空间中的方法
  myinnernamespace::say_hi_inner();
  //声明内层命名空间 : 如果声明了 内层的命名空间 , 可以调用内层命名空间中定义的 say_hi_inner() 方法
  say_hi_inner();
  //域作用符 :: 作用
  //① 调用命名空间中的方法 或 变量
  //② 调用类中的方法 或 成员变量 , ::变量名称 可以访问类中的成员变量
  //方法中的局部变量
  int a_int = 999;
  //域作用符作用
  std::cout << "类中的成员变量 ::a_int : " << ::a_int << " 方法中的局部变量 a_int : " << a_int << std::endl;
  //include 与 命名空间 区别 : 
  // include 的作用 : 将包含的文件 在编译时 拷贝到 这个文件中 , 
  //  如上面 #include "c_extern.h" , 在编译时就将 c_extern.h 头文件中的内容 
  //  全部拷贝到本文件中 使用 #include "c_extern.h" 的位置 
  //命名空间的作用 : 表明后面所有的代码都使用这个命名空间 , 如果调用命名空间中的方法, 
  //  就会去对应的命名空间中查找对应方法; 
  //函数完全重复 : 如果 出现 两个函数 , 其 函数名 参数个数 参数顺序 返回值 完全重复 , 这样就会造成冲突 
  //命名空间作用 : 避免 出现 函数名称 参数及参数顺序 , 返回值 完全相同的情况 , 可以将重复的函数定义在命名空间中 , 这样就能区分两个完全相同的函数 
  return 0;
}


目录
相关文章
|
2月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
147 4
|
3月前
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
62 5
|
3月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
68 1
|
3月前
|
存储 编译器 C语言
深入计算机语言之C++:类与对象(上)
深入计算机语言之C++:类与对象(上)
|
3月前
|
存储 分布式计算 编译器
深入计算机语言之C++:C到C++的过度-2
深入计算机语言之C++:C到C++的过度-2
|
3月前
|
编译器 Linux C语言
深入计算机语言之C++:C到C++的过度-1
深入计算机语言之C++:C到C++的过度-1
|
2月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
60 2
|
2月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
111 5
|
2月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
111 4
|
3月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
35 4