天天看點

【C++ 語言】命名空間 ( namespace | 命名空間定義 | 命名空間嵌套 | 域作用符 | 與 include 對比 )

文章目錄

  • ​​命名空間簡介​​
  • ​​自定義命名空間​​
  • ​​自定義嵌套命名空間​​
  • ​​域作用符​​
  • ​​命名空間 與 include 差別​​
  • ​​命名空間定義與使用完整代碼​​

命名空間簡介

​命名空間 ( namespace ) :​

  • ​1.命名空間簡介 :​ C++ 中的命名空間相當于 Java 中的 Package 包 , 最常用的命名空間是 std , 基本每個項目都要使用 , 代碼如下 :
using namespace std;      
  • ​2.命名空間作用 :​ 平時使用的 ​cout , endl​ 等都是在 ​std 命名空間​ 中定義的 , 如果不聲明 std 命名空間 , 那麼指令行輸出使用的 cout 和 endl 必須使用 ​域作用符 "​

    ​::​

    ​"​ 進行通路 ;
  • ​① 域作用符通路方法 :​ ​命名空間 :: 變量名​
  • ​② 不聲明 std 命名空間使用 cout 方法 :​ ​​

    ​std::cout​

    ​​
  • ​③ 不聲明 std 命名空間使用 endl方法 :​ ​​

    ​std::endl​

    ​​
// 命名空間 相當于 Java 中的 Package 包 , 
  //  上面的 cout endl string 等都定義在 std 命名空間中
  // 如果沒有 using namespace std; 聲明命名空間 , 
  //  那麼必須使用域作用符 "::" ( 兩個冒号 ) , 否則全都會報錯
  std::cout << 
    "沒有使用命名空間 需要使用 std::cout << ... << std::endl 列印" 
    << std::endl;      
  • ​3.執行結果 :​
沒有使用命名空間 需要使用 std::cout << ... << std::endl 列印      
【C++ 語言】命名空間 ( namespace | 命名空間定義 | 命名空間嵌套 | 域作用符 | 與 include 對比 )

自定義命名空間

​自定義命名空間 ( namespace ) :​

  • ​1.定義方式 :​ 使用 ​“namespace 命名空間名稱 {}”​ 格式 , 定義命名空間 , 可以将變量和方法定義在命名空間中 ;
//自定義命名空間
namespace mynamespace {

  //調用時 需要調用 mynamespace::say_hi() 方法進行調用
  void say_hi() {
    //注意 : 下面的 cout 和 endl 定義在 std 命名空間中
    //如果沒有聲明 using namespace std; , 就必須使用域作用符号 "::" 才能通路
    //域作用符格式 : 命名空間::調用内容
    std::cout << "自定義命名空間 mynamespace say_hi() 方法 : Hi!" << std::endl;
  }
}      
  • ​2.聲明自定義的命名空間 :​ 使用 ​“using namespace 命名空間名稱;”​ 聲明命名空間 ; 下面是聲明命名空間 與 不聲明 的差別 :
  • ​① 聲明命名空間 :​ 可以直接調用命名空間中的方法 ;
  • ​② 沒有聲明該命名空間 :​ 就必須使用 ​“命名空間名稱::方法名()”​ 域作用符調用命名空間定義的方法 ;
//聲明自定義的命名空間 , 聲明 外層命名空間 , 
//可以直接調用 say_hi() 方法 ; 
//調用内層的 say_hi_inner() 方法需要使用 myinnernamespace::say_hi_inner() 進行調用
using namespace mynamespace;      
  • ​3.通路命名空間中的方法 ( 沒有聲明的情況下 ) :​ 如果沒有聲明命名空間 , 需要調用 ​“命名空間名稱::方法名()”​ 的方式調用命名空間中的方法 , 這裡想要調用 ​

    ​mynamespace​

    ​​ 命名空間的 ​

    ​say_hi()​

    ​ 方法 , 就需要按照下述代碼進行操作 ;
//沒有聲明命名空間 : 調用自定義的 mynamespace 命名空間中的 say_hi 方法 , 必須使用域作用符
  mynamespace::say_hi();      
  • ​4.通路命名空間中的方法 ( 已經聲明的情況下 ) :​ 如果已經聲明了命名空間 , 就可以直接調用命名空間中的方法 , 不需要使用 域作用符 通路命名空間中的方法 ;
//聲明命名空間 : 如果聲明了 外層的命名空間 , 可以調用外層命名空間中定義的 say_hi() 方法
  say_hi();      
  • ​5.命名空間相關的代碼 :​ 包括 ① 命名空間定義 , ② 聲明 , ③ 使用 ( a. 聲明命名空間 / b. 未聲明命名空間 ) 的代碼 ;
//1.命名空間定義 : 自定義命名空間
namespace mynamespace {

  //調用時 需要調用 mynamespace::say_hi() 方法進行調用
  void say_hi() {
    //注意 : 下面的 cout 和 endl 定義在 std 命名空間中
    //如果沒有聲明 using namespace std; , 就必須使用域作用符号 "::" 才能通路
    //域作用符格式 : 命名空間::調用内容
    std::cout << "自定義命名空間 mynamespace say_hi() 方法 : Hi!" << std::endl;
  }
}

//2. 命名空間聲明
//聲明自定義的命名空間 , 聲明 外層命名空間 , 
//可以直接調用 say_hi() 方法 ; 
//調用内層的 say_hi_inner() 方法需要使用 myinnernamespace::say_hi_inner() 進行調用
using namespace mynamespace;

//下面是方法中的代碼

  //3. 沒有聲明命名空間的情況下調用命名空間中的方法
  //沒有聲明命名空間 : 調用自定義的 mynamespace 命名空間中的 say_hi 方法 , 必須使用域作用符
  mynamespace::say_hi();

  //4. 已經聲明命名空間的情況下調用命名空間中的方法
  //聲明命名空間 : 如果聲明了 外層的命名空間 , 可以調用外層命名空間中定義的 say_hi() 方法
  say_hi();      
  • ​6.代碼執行結果 :​
自定義命名空間 mynamespace say_hi() 方法 : Hi!
自定義命名空間 mynamespace say_hi() 方法 : Hi!      
【C++ 語言】命名空間 ( namespace | 命名空間定義 | 命名空間嵌套 | 域作用符 | 與 include 對比 )

自定義嵌套命名空間

​自定義嵌套命名空間 :​

  • ​1.嵌套命名空間簡介 :​ 命名空間内部再定義一個命名空間 , 這種情況就是嵌套的命名空間 ; 如下代碼 , ​

    ​myinnernamespace​

    ​ 就是定義的内層的命名空間 , 如果要通路内層命名空間的方法 , 需要兩個域作用符才能通路 ;
//命名空間定義 : 自定義命名空間
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;
    }
  }
}      
  • ​2.聲明外層命名空間 :​ 需要使用 ​“using 外層命名空間名稱;”​ 方式進行聲明 ;
//聲明自定義的命名空間 , 聲明 外層命名空間 , 
//可以直接調用 say_hi() 方法 ; 
//調用内層的 say_hi_inner() 方法需要使用 myinnernamespace::say_hi_inner() 進行調用
using namespace mynamespace;      
  • ​3.聲明内層命名空間 :​ 需要使用 ​“using 外層命名空間名稱::内層命名空間名稱;”​ 方式進行聲明 ;
//聲明内層的命名空間 , 需要使用 外層命名空間::内層命名空間 進行聲明
//這樣就可以直接調用内層命名空間的 say_hi_inner() 方法了
using namespace mynamespace::myinnernamespace;      
  • ​4.嵌套命名空間通路 :​ 需要使用兩個域作用符進行通路 , 格式是 ​“外層命名空間::内層命名空間::内層命名空間定義的方法或變量名稱”​ ;
//沒有聲明命名空間 : 嵌套的命名空間調用 , 需要使用兩個域作用符通路最内層命名空間中定義的方法 
  mynamespace::myinnernamespace::say_hi_inner();      
  • ​5.不聲明命名空間的通路方式 :​ 此時就需要完整的使用兩個域作用符通路内層命名空間中的方法或變量 , 代碼如上面的代碼
//沒有聲明命名空間 : 嵌套的命名空間調用 , 需要使用兩個域作用符通路最内層命名空間中定義的方法 
  mynamespace::myinnernamespace::say_hi_inner();      
  • ​6.聲明外層命名空間的通路方式 :​ 此時可以不使用外層的命名空間名稱 , 直接使用 ​“内層命名空間名稱::方法名()”​ 通路内層命名空間中定義的方法 ;
  • ​① 省略外層命名空間 :​ 隻聲明了外層命名空間 , 這裡就可以省略上面的外層命名空間 ;
  • ​② 不能省略内層命名空間 :​ 内層的命名空間不能省略 , 因為沒有聲明内部命名空間 ;
  • ​③ 域作用符個數 :​ 需要一個域作用符通路内層命名空間中的方法 ;
//隻聲明了外層命名空間 , 這裡就可以省略上面的外層命名空間 , 
  //但是内層的命名空間不能省略 , 因為沒有聲明内部命名空間, 
  //需要一個域作用符通路内層命名空間中的方法
  myinnernamespace::say_hi_inner();      
  • ​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!      
【C++ 語言】命名空間 ( namespace | 命名空間定義 | 命名空間嵌套 | 域作用符 | 與 include 對比 )

域作用符

​域作用符 :​

  • ​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      
【C++ 語言】命名空間 ( namespace | 命名空間定義 | 命名空間嵌套 | 域作用符 | 與 include 對比 )

命名空間 與 include 差別

在 C++ 代碼中 , 經常遇到 ​

​#include "c_extern.h"​

​​ 和 ​

​using namespace std;​

​ 代碼 , 兩種方式都可以聲明可使用的若幹變量和方法 ;

  • ​include 作用 :​ 将包含的檔案 在編譯時 拷貝到 這個檔案中 , 如上面 ​

    ​#include "c_extern.h"​

    ​​ , 在編譯時就将 ​

    ​c_extern.h​

    ​​ 頭檔案中的内容 , 全部拷貝到本檔案中 使用 ​

    ​#include "c_extern.h"​

    ​ 的位置 ;
  • ​命名空間的作用 :​ 表明後面所有的代碼都使用這個命名空間 , 如果調用命名空間中的方法, 就會去對應的命名空間中查找對應方法;

​函數完全重複的情況 :​ 如果出現兩個函數 , 其 ① 函數名 ② 參數個數 ③ 參數順序 ④ 傳回值 完全重複 , 這樣就會造成沖突 ;

​命名空間作用 :​ 命名空間就是避免出現上述函數完全重複的情況 , 可以将重複的函數定義在命名空間中 , 這樣就能區分兩個完全相同的函數 ;

命名空間定義與使用完整代碼

// 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++ 相容
  //調用 c_extern.h 頭檔案中定義的方法
  //該方法定義在了 C 語言檔案中
  add(1, 2);


  //2. 引用資料類型
  //代碼 展示 流程 : 
  //① 定義 普通 類型 變量
  int a = 8;
  //② 定義 引用類型變量, 格式 : 類型名稱& 變量名 = 對應類型變量名稱 ;
  int& b = a;
  //③ 調用函數傳入引用類型參數 : 将引用類型傳給接收引用類型的方法
  quote(b);
  //④ 列印引用資料類型的修改結果 , 結果是 b 被修改成了 888
  cout << b << endl;

  //引用資料類型定義與使用 : 
  // ① 引用資料類型定義 : 類型名稱& 變量名 = 對應類型變量名稱 ;
  // ② 引用資料類型的使用方法 : 直接當做原來的變量使用即可, 可以替換原來變量的位置使用

  //引用類型解析 : 
  // ① int& 是引用資料類型 , b 是 a 的引用 
  // ② 配置設定一塊記憶體存放 int 類型資料 8 , 将該記憶體賦予一個别名 a
  // ③ 同時又給該記憶體賦予另外一個别名 b 


  //3. 字元串使用

  //C 字元串

  //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++ 字元串


  // 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. 命名空間
  // 命名空間 相當于 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;
}