目錄
前言
1.缺省參數
2.函數重載
?2.1函數重載的基本規則
?編輯2.2注意事項
2.3 重載解析(Overload Resolution)--補充內容
3.引用
3.1引用的概念和定義
3.2引用的特性
3.3引用的使用
3.4const引用
4.指針和引用的關系
結束語
前言
上節小編講解了命名空間和函數的輸入輸出,本節將講解缺省參數,函數重載等知識。
1.缺省參數
缺省參數是聲明或定義函數時為函數的參數指定一個缺省值。在調用該函數時,如果沒有指定實參,則采用該形參的缺省值,否則使用指定的實參,缺省參數分為全缺省和半缺省參數。(有些地方把缺省參數也叫默認參數)
void func(int a, double b = 3.14, const char* c = "default") { // 正確// 函數體
}void func(int a = 1, double b, const char* c = "default") { // 錯誤,不能跳過 b// 函數體
}
#include <iostream>
using namespace std;
void func(int x=0) {cout << x << endl;
}
int main() {
// 沒有傳參時,使?參數的默認值
// 傳參時,使?指定的實參func();func(10);return 0;
}
運行結果:
0
10
#include <iostream>
using namespace std;
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}
int main()
{Func1();Func1(1);Func1(1, 2);Func1(1, 2, 3);Func2(100);Func2(100, 200);Func2(100, 200, 300);Func2(100, ,300);//錯誤return 0;
}
// 在頭文件中的函數聲明
void func(int a = 1, double b = 3.14, const char* c = "default");// 在源文件中的函數定義
void func(int a, double b, const char* c) {// 函數體
}
2.函數重載
在C++中,函數重載(Function Overloading)是指在同一作用域內可以存在多個同名函數,但這些函數的參數列表(參數的個數、類型或者順序)必須不同。編譯器會根據傳遞給函數的參數來決定調用哪一個重載版本。
?2.1函數重載的基本規則
?
1.參數數量不同:函數可以具有不同數量的參數。
#include <iostream>
using namespace std;
int Add(int a, int b) {return a + b;
}int Add(int a, int b, int c) { return a + b + c;
}int main() {int sum1 = Add(10, 20); double sum2 = Add(10,20,30); cout << "sum1: " << sum1 << endl;cout << "sum2: " << sum2 << endl;return 0;
}
2. 參數類型不同:函數可以具有不同類型的參數。
#include <iostream>
using namespace std;
int add(int a, int b) {cout << "int add(int a, int b)"<<endl;return a + b;}
double add(double a, double b) {cout << "double add(double a, double b)"<<endl;return a + b;}
int main() {int sum1 = add(10, 20); double sum2 = add(1.5, 2.5); cout << "sum1: " << sum1 << endl;cout << "sum2: " << sum2 << endl;return 0;
}
3. 參數順序不同:如果參數類型相同,但順序不同,也可以構成重載。
#include <iostream>
using namespace std;
void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}
int main() {f(10, 'c');f('c', 10);return 0;
}

2.2注意事項
- 返回類型:函數重載與返回類型無關,即不能僅通過改變返回類型來重載函數。
-默認參數:使用默認參數的函數可能會導致重載解析的歧義,應當小心使用。
int Add(int a, int b) {return a + b;
}double Add(int a, int b) { // 錯誤:不能僅通過返回類型來重載return static_cast<double>(a + b);
}
#include <iostream>
using namespace std;// 下?兩個函數構成重載
// f()但是調?時,會報錯,存在歧義,編譯器不知道調?誰
void f()
{cout << "f()" << endl;
}
void f(int a = 10)
{cout << "f(int a)" << endl;
}
int main() {f();return 0;
}
2.3 重載解析(Overload Resolution)--補充內容
當調用一個重載函數時,編譯器會根據提供的實參和每個重載函數的形參列表進行匹配,以確定調用哪一個函數。這個過程稱為重載解析。如果編譯器無法明確地確定應該調用哪個函數,或者找到多個合適的匹配,就會產生編譯錯誤。
函數重載是C++多態性的一種形式,它允許程序員使用相同的名字來執行相似的操作,這增強了代碼的清晰性和可讀性。
3.引用
3.1引用的概念和定義
在 C++ 中,引用是一個變量的別名。一旦一個引用被初始化為指向一個對象,它就不能被重新綁定到另一個對象。這與指針不同,指針可以在任何時候指向不同的對象。
引用的概念
- 別名:引用為另一個變量提供了一個額外的名字,它和原變量指向相同的內存位置。
- 不可變性:一旦引用被初始化,它就不能被重新賦值為另一個變量的引用。
- 無需解引用:使用引用時,不需要像指針一樣使用?
*
?操作符來訪問引用的值。 - 效率:引用在傳遞參數時可以避免不必要的復制,特別是對于大型對象來說,使用引用可以提高效率。
引用的定義
引用在 C++ 中是這樣定義的:
類型 &引用名 = 原變量名;
一些有趣的實例:
這里,類型
?是原變量的類型,&
?符號用于聲明引用,引用名
?是你給引用起的名字,而?原變量名
?是已經存在的變量。
#include <iostream>
using namespace std;
int main() {int a = 520;int& b = a;int& c = a;int& d = b;++d;
// 引?:b和c是a的別名cout << &a << endl;cout << &b << endl;cout << &c << endl;
// 也可以給別名b取別名,d相當于還是a的別名cout << &d << endl;
//地址,值都是一樣的cout << a << endl;cout << b << endl;cout << c << endl;cout << d << endl;return 0;
}
3.2引用的特性
? 引用在定義時必須初始化? 一個變量可以有多個引用? 引用一旦引用一個實體,再不能引用其他實體
#include<iostream>
using namespace std;
int main()
{int a = 10;// 編譯報錯:“ra”: 必須初始化引?//int& ra;int& b = a;int c = 20;// 這?并?讓b引?c,因為C++引?不能改變指向,// 這?是?個賦值b = c;cout << a << endl;cout << b << endl;cout << c << endl;b = 30;cout << &a << endl;cout << &b << endl;cout << &c << endl;cout << a << endl;cout << b << endl;cout << c << endl;return 0;
}
3.3引用的使用
1.引用在實踐中主要是于引用傳參和引用做返回值中減少拷貝提高效率和改變引用對象時同時改變被引用對象。2.引用傳參跟指針傳參功能是類似的,引用傳參相對更方便一些。3.引用返回值的場景相對比較復雜,小編實力有限,以后等知識豐富了再會詳細講解。4.引用和指針在實踐中相輔相成,功能有重疊性,但是各有特點,互相不可替代。C++的引用跟其他語言的引用(如Java)是有很大的區別的,除了用法,最大的點,C++引用定義后不能改變指向,java的引用可以改變指向。5.一些主要用C代碼實現版本數據結構教材中,使用C++引用替代指針傳參,用的是簡化程序,避開復雜的指針。
#include <iostream>
using namespace std;
void Swap(int& x, int& y) {int temp = x;x = y;y = temp;
}
int main() {int x = 520, y = 1314;cout << x << " " << y << endl;Swap(x, y);cout << x << " " << y << endl;return 0;
}
#include<iostream>
#include <assert.h>
#include <stdlib.h> using namespace std;
typedef int STDataType;
typedef struct Stack {STDataType* a;int top;int capacity;
} ST;void STInit(ST& rs, int n = 4) {rs.a = (STDataType*)malloc(n * sizeof(STDataType));rs.top = 0; // 棧頂初始化為 0,表示棧為空rs.capacity = n;
}void STPush(ST& rs, STDataType x) {// 滿了,擴容if (rs.top == rs.capacity) {printf("擴容\n");int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity * sizeof(STDataType));if (tmp == NULL) {perror("realloc fail");return;}rs.a = tmp;rs.capacity = newcapacity;}rs.a[rs.top] = x; rs.top++; // 棧頂指針上移
}int& STTop(ST& rs) {assert(rs.top > 0); // 確保棧不為空return rs.a[rs.top - 1]; // 返回棧頂元素的引用
}int main() {ST st1;STInit(st1);STPush(st1, 1);STPush(st1, 2);cout << STTop(st1) << endl; // 輸出棧頂元素 2STTop(st1) += 10; // 通過引用修改棧頂元素cout << STTop(st1) << endl; // 輸出修改后的棧頂元素 12return 0;
}
3.4const引用
在 C++ 中,
const
?引用是一種特殊類型的引用,它被用來引用一個對象,同時保證這個引用不會修改所引用的對象。這種引用通常用于函數參數,以允許函數讀取傳遞的對象,但不允許通過引用修改它。
以下是?const
?引用的幾個關鍵點:
聲明?const
?引用
const 類型 &引用名 = 引用的對象;
這里,類型
?是被引用對象的類型,引用名
?是你給引用起的名字,而?引用的對象
?是你想要引用的實際對象。
使用?const
?引用的好處
- 保護數據不被修改:通過?
const
?引用,你可以確保傳遞給函數的參數不會被函數修改。- 可以引用臨時對象和字面量:
const
?引用可以引用右值(如字面量或臨時對象),這是非?const
?引用無法做到的。- 可以與任何類型的對象兼容:只要類型可以轉換為?
const
?引用的類型,就可以創建?const
?引用。
示例
不需要注意的是類似 int& rb = a*3; double d = 12.34; int& rd = d; 這樣一些場景下a*3的和結果保存在一個臨時對象中, int& rd = d 也是類似,在類型轉換中會產生臨時對象存儲中間值,也就是時,rb和rd引用的都是臨時對象,而C++規定臨時對象具有常性,所以這里就觸發了權限放大,必須要用常引用才可以。
int main()
{
const int a = 10;
// 編譯報錯:error C2440: “初始化”: ?法從“const int”轉換為“int &”
// 這?的引?是對a訪問權限的放?
//int& ra = a;
// 這樣才可以
const int& ra = a;
// 編譯報錯:error C3892: “ra”: 不能給常量賦值
//ra++;
// 這?的引?是對b訪問權限的縮?
int b = 20;
const int& rb = b;
// 編譯報錯:error C3892: “rb”: 不能給常量賦值
//rb++;
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int a = 10;
const int& ra = 30;
// 編譯報錯: “初始化”: ?法從“int”轉換為“int &”
// int& rb = a * 3;
const int& rb = a*3;
double d = 12.34;
// 編譯報錯:“初始化”: ?法從“double”轉換為“int &”
// int& rd = d;
const int& rd = d;
return 0;
}
#include <iostream>
using namespace std;void print(const int& x) {cout << x << endl;// x = 5; // 錯誤:不能通過 const 引用修改對象
}int main() {int a = 10;const int& ref = a; // 創建一個對 a 的 const 引用// ref = 20; // 錯誤:不能通過 const 引用修改對象print(a); // 正確:傳遞 intprint(20); // 正確:傳遞字面量,通過 const 引用允許return 0;
}
注釋前的錯誤:
正確運行結果:
注意事項
- 一旦?
const
?引用被初始化,它就不能再引用其他對象。 const
?引用不能引用非?const
?對象的地址,如果需要引用非?const
?對象,必須顯式地聲明非?const
?引用。
總之,const
?引用在 C++ 中是一種非常有用的特性,它不僅提供了對數據的保護,還增加了代碼的靈活性和安全性。
4.指針和引用的關系
? 語法概念上引用是一個變量的取別名不開空間,指針是存儲一個變量地址,要開空間。? 引用在定義時必須初始化,指針建議初始化,但是語法上不是必須的。? 引用在初始化時引用一個對象后,就不能再引用其他對象;而指針可以在不斷地改變指向對象。? 引用可以直接訪問指向對象,指針需要解引用才是訪問指向對象。? sizeof中含義不同,引用結果為引用類型的大小,但指針始終是地址空間所占字節個數(32位平臺下占4個字節,64位下是8byte)? 指針很容易出現空指針和野指針的問題,引用很少出現,引用使用起來相對更安全一些。
結束語
本篇博客也就到此結束啦,C++ 的入門也差不多了,下個階段我們將步入類和對象的學習!!!最后支持小編的友友和大佬們點個贊吧,也歡迎大家在評論區多多交流,感謝大家的支持!!!