《C++初階之類和對象》【命名空間 + 輸入輸出 + 缺省參數 + 函數重載】

【命名空間 + 輸入&輸出 + 缺省參數 + 函數重載】目錄

  • 前言:
  • ---------------hello world---------------
    • 比較C語言和C++的第一個程序:hello word
  • ---------------命名空間---------------
    • 什么是命名空間?
    • 怎么使用命名空間?
      • 怎么定義命名空間?
      • 怎么訪問命名空間?
    • C++為什么要引入命名空間?
    • 命名空間怎么就解決了同名標識符互相干擾的難題?
      • 命名沖突的本質是什么?
      • C++的作用域的訪問順序是什么?
    • 命名空間中可以放什么?
    • 命名空間怎么進行嵌套使用?
    • 命名空間的其他注意事項
  • ---------------輸入&輸出---------------
    • C++的輸入&輸出是什么?
    • C++的cin和cout相較于C語言的輸入和輸出有什么優勢?
    • 關于cin和cout還有哪些需要注意事情?
  • ---------------缺省參數---------------
    • 什么是缺省參數?
    • 缺省參數的有哪幾種?
    • 使用缺省參數時的注意事項有哪些?
    • C++中引入缺省參數有什么好處?
  • ---------------函數重載---------------
    • 什么是函數重載?
    • 滿足函數重載的條件有哪些?
    • 還有哪些特殊的函數重載?
    • 函數重載和缺省參數有什么不同?

在這里插入圖片描述

往期《C++初階》回顧:

/------------ 入門基礎 ------------/
【C++的前世今生】

前言:

(。・ω・。)ノ?hi~ 親愛的小伙伴們!(≧?≦)ノ 當芒種的風?呼呼吹過,田間地頭滿是農人播種希望的身影,今天我們也迎來了正式學習 C++ 知識的新旅程了(★ω★)
那么,就讓我們像芒種時節播撒種子一樣,播撒 C++ 這顆種子,期待未來收獲滿滿的編程碩果 🍎?

---------------hello world---------------

比較C語言和C++的第一個程序:hello word

/*------------使用C語言編寫第一個 hello world 代碼------------*/
#include <stdio.h>int main()
{printf("hello world");return 0;
}/*------------使用C++編寫第一個 hello world 代碼------------*/
#include <iostream>   //1.使用#include包含C++的庫
using namespace std;  //2.使用命名空間int main()
{cout << "hello world" << endl;  //3.使用輸出流對象cout向終端控制窗口(小黑窗口) 輸出字符串return 0;
}

---------------命名空間---------------

什么是命名空間?

命名空間(Namespace):是一種將標識符(如:變量、函數、類等)組織成不同作用域,用于組織代碼、避免命名沖突的機制

怎么使用命名空間?

使用命名空間整體上主要是分為兩步:

第一步:定義命名空間

第二步:訪問命名空間

怎么定義命名空間?

namespace 命名空間名稱 
{// 可包含的內容:// - 變量// - 函數// - 類/結構體// - 其他命名空間類型 變量名;返回類型 函數名(參數列表) { /* 函數體 */ }class 類名 { /* 類定義 */ };struct 結構體名 { /* 結構體定義 */ };namespace 子命名空間名 { /* ... */ }
}

怎么訪問命名空間?

在 C++ 中,命名空間(namespace)的使用方式非常靈活,以下是博主精心挑選的三個最實用的命名空間的使用方法,涵蓋從基礎到高級的所有場景:

  1. 直接通過作用域解析符 :: 訪問
  2. 使用 using 聲明(引入特定成員)
  3. 使用 using namespace 指令(引入整個空間)

1. 直接通過作用域解析符 :: 訪問

  • 適用場景:精確控制訪問路徑,避免歧義。
/*----------------------------命名空間的使用----------------------------*/
#include <iostream>
#include <string>/*---------------第一步:命名空間的定義---------------*/
namespace my_space
{string str = "這是我定義的命名空間中的字符串";void fun(){cout << "這是我定義的命名空間中的函數";}
}int main()
{/*---------------第二步:演示如何使用自定義的命名空間中的成員---------------*//*-------------第一種的使用方法:使用作用域解析符訪問-------------*/cout << my_space::str << endl;//printf("%s", my_space::str);  注意:這里你可別使用C語言的printf進行輸出C++風格的字符串//string是C++的字符串對象,printf不能輸出對象這種類型,(仔細回想一下C++中是沒用字符串這種類型的,C語言是使用字符數組存儲字符串的)printf("%s", my_space::str.c_str()); //如果你執意要使用printf進行輸出的話,可以將string通過的函數c_str()轉化為C風格的字符串return 0;
}

在這里插入圖片描述

2. 使用 using 聲明(引入特定成員)

  • 適用場景:需要頻繁使用某個命名空間的少數成員
/*----------------------------命名空間的使用----------------------------*/#include <iostream>
#include <string>
using namespace std;/*---------------第一步:命名空間的定義---------------*/
namespace my_space
{string str = "這是我定義的命名空間中的字符串";void fun(){cout << "這是我定義的命名空間中的函數";}
}using  my_space::str;  // 注意:使用 using 聲明(引入特定成員)必須寫在自定義的命名空間的后面int main()
{/*---------------第二步:演示如何使用自定義的命名空間中的成員---------------*//*-------------第二種的使用方法:使用 using 聲明(引入特定成員)-------------*/cout << str << endl;my_space::fun();return 0;
}

在這里插入圖片描述

3. 使用 using namespace 指令(引入整個空間)

  • 適用場景:短代碼片段或源文件中(頭文件中禁止使用
/*----------------------------命名空間的使用----------------------------*/#include <iostream>
#include <string>
using namespace std;/*---------------第一步:命名空間的定義---------------*/
namespace my_space
{string str = "這是我定義的命名空間中的字符串";void fun(){cout << "這是我定義的命名空間中的函數";}
}using namespace my_space;  // 注意:使用 using namespace 指令(引入整個空間)必須寫在自定義的命名空間的后面int main()
{/*---------------第二步:演示如何使用自定義的命名空間中的成員---------------*//*-------------第三種的使用方法:使用 using namespace 指令(引入整個空間)-------------*/cout << str << endl;fun();return 0;
}

在這里插入圖片描述

看到這里我相信有不少的小伙伴們會想到這行代碼:using namespace std;

這行代碼官方的回答是:將 std 命名空間中的所有成員引入到當前作用域,允許直接使用這些標識符而無需添加 std:: 前綴

簡單點說就是:我們使用namespace定義一個命名空間,就像是在全局作用域這片廣袤的大地上面使用圍墻圍起來一片屬于自己的土地,這片土地有了主人(命名空間的名字)

以后誰再想訪問圍墻里面的東西,必須得到這片土地的主人的同意(指定命名空間的名字進行訪問)

其中有一片土地簡直就是世外桃源,土地的主人名叫std,很多人想去哪里但是每次都要征得同意(添加 std:: 前綴),是不是很麻煩,因此我們使用using namespace std 的感覺就像是:偷了了std的家——暴力將這片土地上的圍墻給拆除了(大型項目中不建議這么做,這將會導致命名空間失去意義),從此大家去世外桃源就是想去就去了!!!

C++為什么要引入命名空間?

當項目規模較大時,不同庫或模塊可能使用相同的名稱 (尤其是當兩名在同一個項目組的程序員合并他倆的代碼的時候,合并之后往往他倆有可能就會打起來),可能會導致命名沖突。

小案例:我寫的變量和庫函數的函數名引發命名沖突

#include <iostream>
#include <stdlib.h>
/*------------任務:定義變量 + 在終端上打印該變量存儲的值------------*/int rand = 100;
int main()
{printf("%d", rand); //error:“rand”: 重定義;以前的定義是“函數”return 0;
}

在這里插入圖片描述

而為了讓大家能和睦相處,因此C++ 引入了命名空間機制,它通過邏輯隔離的方式,確保不同作用域內的同名標識符不會互相干擾,從而讓代碼協作更加和諧高效。

小案例:使用命名空間避免命名沖突

#include <iostream>
#include <stdlib.h>
/*------------任務:定義變量 + 在終端上打印該變量存儲的值------------*/namespace my_space
{int rand = 100;
}int main()
{printf("%d", rand); //error:“rand”: 重定義;以前的定義是“函數”return 0;
}

在這里插入圖片描述

命名空間怎么就解決了同名標識符互相干擾的難題?

為了回答這個問題,我們要對 作用域 有一定的理解,那先從C語言說起吧:

關于C語言的作用域有哪些,不同的人會給出不同的劃分種類,但是從本質上理解C語言就兩個作用域:函數局部作用域全局作用域

因為一個C程序中所有的變量、函數存在的位置無非就是:函數局部作用域全局作用域

(其中函數只能存儲于全局作用域中)


而這時候我們就要仔細思考:是C語言的哪些不足導致了上面的命名沖突的情況,而使得C++不得不引入命名空間

回答:由于C語言的作用域過于單一,當項目規模較大時,會有大量的變量、函數都存在于全局作用域中,這樣的話就可能會導致很多命名沖突。

(在同一個函數作用域中一般我們不會使用相同的標識符進行命名)

所以C++的思路是:可不可以從全局作用域中再分出去一些域,所以就有了C++四大作用域:

  1. 函數局部作用域
  2. 命名空間作用域
  3. 類域
  4. 全局作用域

為解決這個問題,我們還要了解:

  • 命名沖突的本質是什么?
  • C++的作用域的訪問順序是什么?

命名沖突的本質是什么?

命名沖突(Name Conflict):在同一作用域內使用相同的標識符:變量名、函數名、類名等),導致編譯器無法區分它們的情況。


注意:這里我們要抓住核心的的名詞:“同一作用域 + 相同的標識符”

所以這也就好理解為什么:C++又在C語言的基礎上又創建了兩個作用域

C++的作用域的訪問順序是什么?

在 C++ 中,當訪問一個標識符時,編譯器會按照特定的順序查找該標識符的定義,這個過程稱為 名稱查找(Name Lookup)

理解這個順序對于避免命名沖突和理解代碼行為至關重要。

名稱查找順序:

  1. 局部作用域(Block Scope):首先在當前函數的局部作用域中查找標識符,包括在當前塊(如:if 語句、for 循環等)中定義的變量。
  2. 類作用域(Class Scope):如果在局部作用域中沒有找到標識符,那么會在包含當前函數的類的成員作用域中查找。(如果當前函數是類的成員函數的話)
  3. 命名空間作用域(Namespace Scope):如果在類作用域中沒有找到標識符,那么會在當前命名空間中查找。(如果定義的有命名空間的話)
  4. 全局作用域(Global Scope):如果在上面的作用域中都沒有找到標識符,那么就會在全局作用域中查找。
  5. std 命名空間:在 C++ 中,std 是一個特殊的命名空間,包含了標準庫的所有內容。如果在全局作用域中沒有找到標識符,那么會檢查 std 命名空間。

綜上所述:這樣做我們就是實現了:對標識符的名稱進行本地化,以避免命名沖突或名字污染。也就是說:雖然咱倆寫的標識符的名稱相同,但是代碼合并后重名的標識符不再是在同一個作用域:全局作用域 ,而是現在在不同的作用域:不同的 命名空間作用域,所以不構成命名沖突。

所以合并完代碼之后咱倆還是好朋友🐶

命名空間中可以放什么?

/*------------C++的命名空間使用------------*/
#include <stdio.h>
#include <stdlib.h>/*------------定義一個的命名空間:my_utils------------*/
namespace my_utils
{//1.命名空間中可以定義:變量int rand = 100;  //定義變量(故意與標準庫rand函數同名)//2.命名空間中可以定義:函數int add(int left, int right){return left + right;}//3.命名空間中可以定義:自定義數據類型struct SingleListNode{int data;struct SingleListNode* next;};
}
int main()
{//1.使用默認訪問(全局命名空間訪問):這里訪問的是全局的標準庫中rand函數地址printf("%p\n", rand);printf("%p\n", ::rand);//2.使用指定域(my_utils命名空間)訪問:這里訪問是my_utils命名空間的rand變量的值printf("%d\n", my_utils::rand);return 0;/* * 關鍵點說明:* 1. ::rand		 - 訪問全局命名空間的rand(標準庫函數)* 2. my_utils::rand - 訪問my_utils命名空間的rand變量* 3. 實際開發中應避免與標準庫同名*/
}

命名空間怎么進行嵌套使用?

/*------------命名空間的嵌套使用------------*/
#include <stdio.h>/*------------定義一個的命名空間:school------------*/
//1.外層命名空間:school
namespace school
{//2.內層命名空間1:teacher_anamespace teacher_a{//2.1:定義變量int rand = 50;//2.2:定義函數int add(int left, int right){return left + right;}}//2.內層命名空間2:teacher_bnamespace teacher_b{//2.1:定義變量int rand = 100;//2.2:定義函數int add(int left, int right){return (left + right) * 10; //將結果放大原來的10倍}}
}
int main()
{/*------------訪問嵌套命名空間中的成員------------*/// 1. 訪問不同命名空間中的同名變量printf("teacher_a的rand值: %d\n", school::teacher_a::rand);  // 輸出50printf("teacher_b的rand值: %d\n", school::teacher_b::rand);  // 輸出100// 2. 調用不同命名空間中的同名函數printf("teacher_a的加法結果(1+2): %d\n",school::teacher_a::add(1, 2));  // 輸出3(1+2)printf("teacher_b的加法結果(1+2): %d\n",school::teacher_b::add(1, 2));  // 輸出30((1+2)*10)return 0;
}

在這里插入圖片描述

命名空間的其他注意事項

命名空間還有很多可以單獨拎出來講的東西:博主這里就精挑一些我們平時使用命名空間需要注意事項來講一下:

命名空間與頭文件的關系

  • 避免在頭文件中使用 using namespace:可能導致命名沖突擴散到包含該頭文件的所有代碼。

    // myheader.h (錯誤示例!)
    using namespace std;  // ? 污染所有包含該頭文件的源文件
    

命名空間的全局可見性

  • 不同文件的同名命名空間會自動合并

    // File1.cpp
    namespace Shared 
    {void func1();
    }// File2.cpp
    namespace Shared  //與File1中的Shared合并
    {  void func2();
    }
    

---------------輸入&輸出---------------

C++的輸入&輸出是什么?

cincout:是 C++ 標準庫中用于標準輸入輸出的流對象,用于實現控制臺程序的輸入和輸出操作。

  • 它們定義在 <iostream> 頭文件中。
  • 它們屬于 std 命名空間。

標準輸入流 (cin):對應鍵盤輸入,類型為 istream

  • cin 通過 提取運算符 (>>) 從鍵盤讀取數據到變量

標準輸出流 (cout):對應控制臺輸出,類型為 ostream

  • cout 通過 插入運算符 (<<) 將數據輸出到控制臺

它們是面向對象的 I/O 方式,比 C 語言的 scanfprintf 更安全、更靈活。

C++的cin和cout相較于C語言的輸入和輸出有什么優勢?

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;int main()
{//1.定義各種類型的變量int a;double b;char c;printf("-------------使用C風格進行輸入&輸出-------------\n");//2.使用C風格進行輸入賦值scanf("%d %lf %c ", &a, &b, &c);//3.使用C風格進行輸出printf("%d %lf %c\n", a, b, c);cout << "-------------使用C++風格進行輸入&輸出-------------" << endl;//4.使用C++風格進行輸入賦值cin >> a >> b >> c;//5.使用C++風格進行輸出cout << a << " " << b << " " << c << " " << endl;return 0;
}

在這里插入圖片描述

特性scanf / printfcin / cout
類型安全? 需手動匹配格式符?? 自動類型推導
擴展性? 僅支持基本類型?? 支持自定義類型的 <<>>
性能?? 更快?? 稍慢(同步問題)

關于cin和cout還有哪些需要注意事情?

<<: 運算符可連續使用,按順序輸出表達式的值

endl: 是一個函數,流插入輸出時,相當于插入一個換行符,同時刷新輸出緩沖區(立即顯示內容)

\n: 僅換行,不強制刷新緩沖區(性能略優,但需注意輸出時機)


>>:自動跳過空白字符(空格、制表符、換行符),并嘗試將輸入轉換為目標類型。

  • 讀取字符串時,cin 默認在遇到空格時停止,因此無法讀取包含空格的完整名稱(Alice Smith 會被截斷為 Alice
功能語法說明
輸出cout << value;使用 << 插入運算符,支持鏈式調用
輸入cin >> variable;使用 >> 提取運算符,跳過空白字符
讀取整行getline(cin, str);讀取包含空格的字符串
格式化輸出cout << setprecision(2);需要 <iomanip> 頭文件

coutcin 為保證類型安全,性能略低于 C 的 printfscanf

可通過以下三句話可以將cin和cout的輸入輸出速度提升2-3倍

ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);

下面是算法競賽中常用的解綁三件套的模板和詳細的注釋:

#include <iostream>
using namespace std;int main()
{/* ==============================================* 【IO性能優化關鍵代碼】*  以下三行用于提高C++標準IO流的執行效率*  適用于需要高速IO的場景(如算法競賽)* ==============================================*//*----------第一步:關閉C++標準流與C標準庫的同步----------*/// - 默認情況下,C++的cin/cout與C的stdin/stdout保持同步以保證混用時的安全性// - 關閉后可以提高速度,但不能再混用C/C++的IO函數(如:printf/cin混用)ios_base::sync_with_stdio(false);/*----------第二步:解綁cin與cout的關聯----------*/// - 默認情況下,cin操作會先自動刷新cout的緩沖區(保證交互式程序的正確性)// - 解綁后進一步提升速度,但需要手動控制緩沖區刷新(如:用endl或flush)cin.tie(nullptr);/*----------第三步:解綁cout與cerr/clog的關聯(非必須,但某些編譯器需要)----------*/// - 進一步減少不必要的緩沖區同步cout.tie(nullptr);/* ==============================================* 【注意事項】*  使用這些優化后:*  1. 禁止混用C/C++的IO函數(如不能用printf + cin)*  2. 需要顯式刷新緩沖區(如cout << endl;)*  3. 適用于純C++ IO且數據量大的場景(如:10萬+次讀寫)* ==============================================*/return 0;
}

---------------缺省參數---------------

什么是缺省參數?

缺省參數(Default Arguments):是指在函數聲明定義時為參數指定一個默認值。

  • 當函數調用時,如果沒有為該參數傳遞實際參數,就會使用這個默認值。

缺省參數的語法返回類型 函數名(類型 參數名 = 默認值);

缺省參數的使用案例:

/*--------------------------C++的缺省參數--------------------------*/
#include <iostream>
using namespace std;/*------------簡單的了解缺省參數------------*/void Func(int a = 0)  // 參數a的默認值為0
{// 輸出參數a的值cout << "a = " << a << endl;
}int main()
{//情況1:不傳遞參數,使用默認值cout << "調用Func():" << endl;Func();    // 等效于Func(0)// 輸出結果:a = 0//情況2:傳遞明確參數值cout << "\n調用Func(10):" << endl;Func(10);  // 覆蓋默認值,a被賦值為10// 輸出結果:a = 10return 0; 
}

在這里插入圖片描述

缺省參數的有哪幾種?

全缺省參數:函數的所有參數都有默認值

半缺省參數:函數的部分參數有默認值,且有默認值的參數必須放在形參列表的右側

  • 從右往左依次連續缺省,不能間隔跳躍給缺省值

全缺省參數和半缺省參數的使用案例:

/*------------------全缺省參數and半缺省參數------------------*//*** @brief 演示全缺省參數的函數* @param a 第一個參數,默認值為10* @param b 第二個參數,默認值為20* @param c 第三個參數,默認值為30* @note* - 全缺省參數:所有參數都有默認值* - 調用時可傳遞0~3個參數* - 缺省參數必須從右向左連續定義*/
void Func1(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a;cout << " b = " << b;cout << " c = " << c << endl;
}/*** @brief 演示半缺省參數的函數* @param a 必須傳入的參數(無默認值)* @param b 可選參數,默認值為10* @param c 可選參數,默認值為20* @note* - 半缺省參數:部分參數有默認值* - 必須從右向左連續缺省* - 調用時至少傳遞1個參數(對應a)*/
void Func2(int a, int b = 10, int c = 20)
{cout << "a = " << a;cout << " b = " << b;cout << " c = " << c << endl;
}int main()
{// 測試Func1的全缺省調用cout << "----- Func1全缺省測試 -----" << endl;Func1();        // 使用全部默認值:a=10, b=20, c=30Func1(1);       // a=1, b和c用默認值:b=20, c=30Func1(1, 2);    // a=1, b=2, c用默認值:c=30Func1(1, 2, 3); // 覆蓋所有默認值:a=1, b=2, c=3// 測試Func2的半缺省調用cout << "----- Func2半缺省測試 -----" << endl;Func2(100);         // a必須傳值:a=100, b和c用默認值:b=10, c=20Func2(100, 200);    // a=100, b=200, c用默認值:c=20Func2(100, 200, 300); // 覆蓋所有參數:a=100, b=200, c=300return 0;
}

在這里插入圖片描述

使用缺省參數時的注意事項有哪些?

特性說明示例
從右向左連續缺省參數必須從參數列表最右側開始連續定義void func(int a, int b=1, int c=2) ??
void func(int a=0, int b) ?
調用時從左匹配實參按從左到右順序匹配形參,不能跳過參數func(10)a=10,b=1,c=2
func(10,20)a=10,b=20,c=2
單次定義原則如果函數在頭文件中聲明并指定了缺省參數,在源文件中定義時不能再重復指定缺省參數,否則會導致重復定義錯誤。頭文件:void foo(int x=5);
源文件:void foo(int x) {...}

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

C++中引入缺省參數有什么好處?

疑問:可能有很多的小伙伴們在學習了缺省參數后,會感慨它有什么用處呢?

有這樣的疑問是很正常的,接下來博主將使用C++的缺省參數重新實現一下我們在《數據結構初階》中學習的順序棧的其中的一個接口函數:順序棧的初始化,帶你領略一下缺省參數的牛逼厲害之處。

------------------------------Stack.h-------------------------------
#include <iostream>
#include <assert.h>
using namespace std;typedef int STKDataType;
typedef struct Stack
{STKDataType* a;int top;int capacity;
}STK;void STKInit(STK* pstk, int n = 4); //這里稍微注意一下;由于單次定義原則所以我們一般在函數聲明時指定缺省參數------------------------------Stack.cpp-----------------------------#include "Stack.h"void STKInit(STK* pstk, int n) //缺省參數不能聲明和定義同時給,所以定義時候我們沒有給缺省參數
{assert(pstk);assert(n > 0);pstk->a = (STKDataType*)malloc(n * sizeof(STKDataType));pstk->top = 0;pstk->capacity = n;
}------------------------------Test.cpp-----------------------------#include "Stack.h"int main()
{STK s1;STKInit(&s1);//確定知道要插入1024個數據, 初始化時一把開好, 避免擴容STK s2;STKInit(&s2, 1024);return 0;
}

通過閱讀上面的代碼,小伙伴們你們是不是已經體會到缺省參數的好處了呢?

是不是在之前無論我們是否知道棧的初始空間的大小,棧的空間都要經過從4、8、16、32、……、二倍二倍的進行擴容的一個過程。

但是如果我們事先已經知道了棧的存儲空間,例如是1024字節,那么是不是我們可以在定義棧的時候就一次性的將空間開辟好,也就相當于省去了10次擴容的時間消耗對吧,所以說缺省參數是很有價值的。

---------------函數重載---------------

什么是函數重載?

函數重載(Function Overloading):是指在同一個作用域內,可以有多個同名函數,但是這些函數的參數列表(參數個數參數類型參數順序)必須不同 。

  • 編譯器根據函數調用時提供的實參信息來確定具體調用哪個函數。
  • 函數的返回值類型不能作為函數重載的依據。

滿足函數重載的條件有哪些?

規則說明正確案例
參數個數不同在同一作用域內,同名函數的參數個數必須有差異,這樣編譯器才能根據調用時傳入參數的數量來區分調用哪個函數int add(int a, int b);
int add(int a, int b, int c);
參數類型不同同名函數的參數類型至少有一個不一樣,編譯器依據實參類型匹配對應的函數版本int add(int a, int b);
double add(double a, double b);
參數順序不同同名函數的參數順序不一致,也可構成重載,編譯器會根據參數傳入順序判斷調用哪個函數void print(int num, char ch);
void print(char ch, int num);

注意事項僅返回值類型不同不能構成函數重載

在這里插入圖片描述

三種函數重載的示例:

/*-------------------------三種函數重載的案例-------------------------*/
#include <iostream>
using namespace std;/*------------------重載案例1:參數個數不同------------------*//*** @brief 無參版本函數*/
void f()
{cout << "調用 f()" << endl;
}/*** @brief 單參版本函數* @param a 整型參數*/
void f(int a)
{cout << "調用 f(int a)" << endl;
}/*------------------重載案例2:參數類型不同------------------*/
/*** @brief 函數重載示例2:參數類型不同* @param left 第一個整數操作數* @param right 第二個整數操作數* @return 兩數之和* @note 與下面的double版本構成重載*/
int add(int left, int right)
{cout << "調用 int add(int left, int right)" << endl;return left + right;
}/*** @brief 函數重載示例2:參數類型不同* @param left 第一個浮點數操作數* @param right 第二個浮點數操作數* @return 兩數之和* @note 與上面的int版本構成重載*/
double add(double left, double right)
{cout << "調用 double add(double left, double right)" << endl;return left + right;
}/*------------------重載案例3:參數順序不同------------------*/
/*** @brief 參數順序:int在前,char在后*/
void f(int a, char b)
{cout << "調用 f(int a, char b)" << endl;
}/*** @brief 參數順序:char在前,int在后*/
void f(char b, int a)
{cout << "調用 f(char b, int a)" << endl;
}int main()
{// 測試參數個數不同的重載f();        // 調用無參版本f(10);      // 調用int參數版本// 測試類型不同的重載add(10, 20);        // 調用int版本add(10.1, 20.2);    // 調用double版本// 測試參數順序不同的重載f(10, 'a'); // 調用(int, char)版本f('a', 10); // 調用(char, int)版本return 0;
}

在這里插入圖片描述

還有哪些特殊的函數重載?

規則說明正確案例
const 修飾符差異函數參數的頂層 const(如const int)不能構成重載,但底層 const(如int* const vs const int*)可以void func(int* ptr);
void func(const int* ptr);
(底層 const 不同)
指針類型差異函數參數為不同類型的指針(如普通指針與常量指針)可以構成重載void func(int* ptr);
void func(int* const ptr);
(頂層 const 不同)
引用與值類型差異函數參數為值類型和引用類型可以構成重載void func(int a);
void func(int& a);
成員函數的 const 重載類的成員函數是否為 const 可以構成重載,用于區分對常量對象和非常量對象的調用int getValue() const;
int getValue();
模板參數實例化不同函數模板通過不同的模板參數實例化可以生成重載函數template<typename T> void func(T a);
template<> void func(int a);(顯式特化)

注意:對于初學C++的萌新這里可以先作為了解,不作為掌握的內容。

函數重載和缺省參數有什么不同?

函數重載與缺省參數二者都能實現靈活調用函數,但原理不同。

  • 函數重載:是多個同名函數,參數列表不同。

  • 缺省參數:是一個函數,參數有默認值。

特性缺省參數函數重載
實現方式單一函數擴展參數多個同名函數
適用場景參數有明確默認值參數類型/數量有本質差異
靈活性行為一致,僅參數值變化可完全改變函數行為

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85822.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85822.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85822.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[USACO1.5] 八皇后 Checker Challenge Java

import java.util.*;public class Main {// 標記 對角線1&#xff0c;對角線2&#xff0c;所在x軸 是否存在棋子static boolean[] d1 new boolean[100], d2 new boolean[100], d new boolean[100]; static int n, ans 0;static int[] arr new int[14]; // 記錄一輪棋子位置…

云服務器Xshell登錄拒絕訪問排查

根據你的描述&#xff0c;使用Xshell 8登錄云服務器時顯示“拒絕訪問”&#xff0c;可能涉及多個原因。以下結合搜索結果整理出排查和解決方法&#xff0c;按優先級排序&#xff1a; 一、檢查基礎網絡與端口連通性 本地網絡與服務器IP是否可達 在本地電腦的CMD中執行 ping 服務…

Python爬蟲實戰:研究urlunparse函數相關技術

1. 引言 1.1 研究背景與意義 在當今信息爆炸的時代,互聯網上的數據量呈現出指數級增長。如何從海量的網頁數據中高效地獲取有價值的信息,成為了學術界和工業界共同關注的問題。網絡爬蟲作為一種自動獲取網頁內容的技術,能夠按照預定的規則遍歷互聯網上的網頁,并提取出所需…

Spring AI學習一

隨著Chatpt的火爆&#xff0c;現在Spring官方也開始支持AI了并推出了Spring AI框架&#xff0c;目前還沒發布正式版本&#xff0c;這里可以先看一下官方依賴的版本。 Spring官網地址可以看這里&#xff1a;Spring | Home 目前官網上是有這兩個版本&#xff1a;1.0.0和1.1.0-SN…

reverse筆記

一&#xff0c;strcat的使用方法&#xff08;在攻防世界中刷題時遇到的&#xff09; 二&#xff0c;殼&#xff08;做題遇到過但是一直不是很理解&#xff0c;今天查了一下&#xff09; 殼是一種軟件保護技術&#xff0c;能夠防止程序被輕易地分析和修改。 總而言之&#xff0…

spring4第7-8課-AOP的5種通知類型+切點定義詳解+執行順序

繼續學習&#xff0c;方便自己復查記錄 ①AOP簡介&#xff1a; 面向切面編程(也叫面向方面編程)&#xff1a;Aspect Oriented Programming(AOP)。 Spring框架中的一個重要內容。。 通過預編譯方式和運行期間動態代理實現在不修改源代碼的情況下給程序動態統一添加功能…

EscapeX:去中心化游戲,開啟極限娛樂新體驗

VEX 平臺推出全新去中心化游戲 EscapeX&#xff08;數字逃脫&#xff09;&#xff0c;創新性地將大逃殺玩法與區塊鏈技術相融合。用戶不僅能暢享緊張刺激的解謎過程&#xff0c;更能在去中心化、公正透明的環境中參與游戲。EscapeX 的上線&#xff0c;為 VEX 生態注入全新活力&…

Multi Agents Collaboration OS:Web DeepSearch System

背景&#xff1a;多智能體協作驅動網絡信息處理的范式革新 隨著大型語言模型&#xff08;LLM&#xff09;能力的突破性進展&#xff0c;人工智能正從“單點賦能”向“系統協同”演進。傳統單一智能體在復雜業務場景中逐漸顯露局限&#xff1a;面對需多維度知識整合、動態任務拆…

React 第五十三節 Router中 useRouteError 的使用詳解和案例分析

前言 useRouteError 是 React Router v6.4 引入的關鍵錯誤處理鉤子&#xff0c;用于在 路由錯誤邊界&#xff08;Error Boundary&#xff09; 中獲取路由操作過程中發生的錯誤信息。 它提供了優雅的錯誤處理機制&#xff0c;讓開發者能夠創建用戶友好的錯誤界面。 一、useRou…

[arthas]arthas安裝使用

arthas是阿里開源的一個java線上監控以及診斷工具&#xff0c;在docker容器中我們無需重啟服務&#xff0c;也不用更改代碼&#xff0c;就可以完成對應用內存、線程、日志級別的修改、方法調用的出入參、異常監測、執行耗時等&#xff0c;xxxx.xxxx.xxxxx為脫敏內容 1. 在docke…

Flask-Babel 使用示例

下面創建一個簡單的 Flask-Babel 示例&#xff0c;展示如何在 Flask 應用中實現國際化和本地化功能。這個示例將包括多語言支持&#xff08;中文和英文&#xff09;、語言切換功能以及翻譯文本的使用。 項目結構 我們將創建以下文件結構&#xff1a; 1. 首先&#xff0c;創…

[論文閱讀] 軟件工程 | 量子計算如何賦能軟件工程(Quantum-Based Software Engineering)

arXiv:2505.23674 [pdf, html, other] Quantum-Based Software Engineering Jianjun Zhao Subjects: Software Engineering (cs.SE); Quantum Physics (quant-ph) 量子計算如何賦能軟件工程 我們在開發軟件時&#xff0c;常常會遇到一些棘手的問題。比如&#xff0c;為了確保軟…

Ansible 進階 - Roles 與 Inventory 的高效組織

Ansible 進階 - Roles 與 Inventory 的高效組織 如果說 Playbook 是一份完整的“菜譜”,那么 Role (角色) 就可以被看作是制作這道菜(或一桌菜)所需的標準化“備料包”或“半成品組件”。例如,我們可以有一個“Nginx Web 服務器安裝配置 Role”、“MySQL 數據庫基礎設置 Ro…

青少年編程與數學 01-011 系統軟件簡介 04 Linux操作系統

青少年編程與數學 01-011 系統軟件簡介 04 Linux操作系統 一、Linux 的發展歷程&#xff08;一&#xff09;起源&#xff08;二&#xff09;早期發展&#xff08;三&#xff09;成熟與普及&#xff08;四&#xff09;移動與嵌入式領域的拓展 二、Linux 的內核與架構&#xff08…

將圖形可視化工具的 Python 腳本打包為 Windows 應用程序

前文我們已經寫了一個基于python的tkinter庫和matplotlib庫的圖形可視化工具。 基于Python的tkinter庫的圖形可視化工具&#xff08;15種圖形的完整代碼&#xff09;:基于Python的tkinter庫的圖形可視化工具&#xff08;15種圖形的完整代碼&#xff09;-CSDN博客 在前文基礎上&…

【Kotlin】簡介變量類接口

【Kotlin】簡介&變量&類&接口 【Kotlin】數字&字符串&數組&集合 【Kotlin】高階函數&Lambda&內聯函數 【Kotlin】表達式&關鍵字 文章目錄 Kotlin_簡介&變量&類&接口Kotlin的特性Kotlin優勢創建Kotlin項目變量變量保存了指向對…

OpenCV種的cv::Mat與Qt種的QImage類型相互轉換

一、首先了解cv::Mat結構體 cv::Mat::step與QImage轉換有著較大的關系。 step的幾個類別區分: step:矩陣第一行元素的字節數step[0]:矩陣第一行元素的字節數step[1]:矩陣中一個元素的字節數step1(0):矩陣中一行有幾個通道數step1(1):一個元素有幾個通道數(channel()) cv::Ma…

搭建基于VsCode的ESP32的開發環境教程

一、VsCode搜索ESP-IDF插件 根據插件處搜索找到ESP-IDF并安裝 安裝完成 二、配置安裝ESP-IDF 配置IDF 按照如下配置&#xff0c;點擊安裝 安裝完成 三、使用案例程序 創建一個閃光燈的例子程序&#xff0c;演示程序編譯下載。 選擇blink例子&#xff0c;閃爍LED的程序 選…

企業培訓學習考試系統源碼 ThinkPHP框架+Uniapp支持多終端適配部署

在數字化轉型浪潮下&#xff0c;企業對高效培訓與精準考核的需求日益迫切。一套功能完備、多終端適配且易于定制的培訓學習考試系統&#xff0c;成為企業提升員工能力、檢驗培訓成果的關鍵工具。本文給大家分享一款基于 ThinkPHP 框架與 Uniapp 開發的企業培訓學習考試系統&…

【PmHub面試篇】PmHub集成Redission分布式鎖保障流程狀態更新面試專題解析

你好&#xff0c;歡迎來到本次關于PmHub整合TransmittableThreadLocal (TTL)緩存用戶數據的面試系列分享。在這篇文章中&#xff0c;我們將深入探討這一技術領域的相關面試題預測。若想對相關內容有更透徹的理解&#xff0c;強烈推薦參考之前發布的博文&#xff1a;【PmHub后端…