函式探幽 函式過載(含過載引用引數)

2021-10-08 03:12:56 字數 4338 閱讀 7307

函式過載讓您能夠使用多個同名的函式。

我們可以通過函式過載來設計一系列函式——它們完成相同的工作,但使用不同的引數列表。

函式過載的關鍵是函式的引數列表——也稱為函式特徵標(function signature)。

如果兩個函式的引數數目和型別相同,同時引數的排序順序也相同,則它們的特徵標相同,

而變數名時無關緊要的。c++允許定義名稱相同的函式,條件是它們的特徵標不同。

如果引數數目和/或引數型別不同,則特徵標也不同。例如,可以定義一組原型如下的print( )函式:

void print (const char * str, int width); //#1

void print (double d, int width); //#2

void print (long l, int width); //#3

void print (int i, int width); //#4

void print(const char str); //#5

使用print()函式時,編譯器將根據採取的用法使用有相應特徵標的原型:

print(「pancakes」, 15); //use #1

print(「syrup」); //use #5

print(1999.0, 10); //use #2

print(1999, 12); //use #4

print(1999l, 15); //use #3

例如,print(「pancakes」, 15)使用乙個字串和乙個整數作為引數,這與#1原型匹配。

使用被過載的函式時,需要在函式呼叫中使用正確的引數型別。例如,對於下面的語句:

unsigned int year = 3210;

print(year, 6); //ambiguous call

print()不與任何原型匹配。沒有匹配的原型並不會自動停止使用其中的某個函式,因為c++嘗試使用標準型別轉換強制進行匹配。如果#2原型是print( )唯一的原型,則函式呼叫print(year,6)將把year轉換為double型別。但在上面的**中,有3個將數字作為第乙個引數的原型,因此有3中轉換year的方式。在這種情況下,c++將拒絕這種函式呼叫,並將其視為錯誤。

一些看起來彼此不同的特徵標是不能共存的。

例如,請看下面的兩個原型:

double cube (double x);

double cube (double & x);

假如有下面的**:

cout << cube (x);

引數x與double x原型和double &x原型都匹配,因此編譯器無法確定究竟應使用哪個原型。為避免這種混亂,編譯器在檢查函式特徵標時,將把型別引用和型別本身視為同乙個特徵標。

匹配函式時,並不區分const和非const 變數。

請看下面的原型:

void dribble (char * bits); //overloaded

void dribble (const char * cbits); //overloaded

void dabble (char * bits); //not overloaded

void drivel (const char * bits); //not overloaded

下面列出了各種函式呼叫對應的原型:

const char p1 [20] = 「how』s the weather?」;

char p2[20] = 「how』s business?」;

dribble(p1); //dribble(const char );

dribble(p2); //dribble(char );

dabble(p1) //not match

dabble (p2); //dabble(char )

drivel(p1); //drivel(const char );

drivel(p2); //drivel(const char );

dribble( )函式有兩個原型,乙個用於const指標,另乙個用於常規指標,編譯器根據實參是否為const來決定使用哪個原型。dribble()函式只與帶非const引數的呼叫匹配,而drivel()函式可以與帶const或非const引數的呼叫匹配。drivel()和dabble()之所以在行為上有這種差別,主要是由於將非const值賦給const變數是合法的,但反之則是非法的。

請記住,是特徵標,而不是函式型別使得可以對函式進行過載。例如,下面的兩個宣告是互斥的:

long gronk (int n, float m); //same signatures

double gronk(int n, float m); //hence not allowed

因此,c++不允許以這種方式過載gronk()。返回型別可以不同,但特徵標也必須不同:

long gronk (int n, float m); //different signatures,

double gronk(float n, float m ); //hence allowed

類設計和stl經常使用引用引數,因此知道不同引用型別的過載很有用。請看下面的三個原型:

void sink (double & r1); //matches modifiable lvalue

void sank (const double & r2); //matches modifiable or const lvalue, rvalue

void sunk (double && r3); //matches rvalue

左值引用引數r1與可修改的左值引數(如double變數)匹配;

const左值引用引數r2與可修改的左值引數、const左值引數和右值引數(如兩個double值的和)匹配;

最後,左值引用引數r3與左值匹配。注意到與r1和r3匹配的引數都與r2匹配。

這就帶來了乙個問題:如果過載使用這三種引數的函式,結果將如何?答案是將呼叫最匹配的版本:

void staff (double & rs); //matches modifiable lvalue

void staff (const double & rcs) //matches rvalue, const lvalue

void stove(double & r1); //matches modifiable lvalue

void stove(const double & r2); //matches const lvalue

void stove(double && r3); //matches rvalue

這讓您能夠根據引數是左值,const還是右值來定製函式的行為:

double x = 55.5;

const double y = 32.0;

stove(x); //calls stove(double &)

stove(y); //calls stove(const double &)

stove(x+y); //calls stove (double &&)

如果沒有定義函式stove(double &&), stove(x+y)將呼叫函式stove(const double &).

何時使用函式過載

僅當函式基本上執行相同的任務,但是用不同形式的資料時,才應採用函式過載。

c++如何跟蹤每乙個過載函式呢?它給這些函式指定了秘密身份。

使用c++開發工具中的編輯器編寫和編譯程式時,c++編譯器將執行一些神奇的操作——名稱修飾

(name decoration)或名稱矯正(name mangling),它根據函式原型中指定的形參型別對每個函式名進行加密。

請看下述未經修飾的函式原型:

long myfunctionfoo(int, float);

這種格式對於人類來說很適合;我們知道函式接受兩個引數(乙個為int型別,另乙個為float型別),

並返回乙個long值。而編譯器將名稱轉換為不太好看的內部表示,來描述該介面,如下所示:

?myfunctionfoo@@yaxh

對原始名稱的表面看來無意義的修飾(或矯正)將對引數數目和型別進行編碼。

新增的一組符號隨函式特徵標而異,而修飾時使用的約定隨編譯器而異。

by——suki

from《c++ primer plus》

過載引用引數 函式模板

void sink double r1 matches modifiable lvalue void sank const double r2 matches modifiable or const lvalue,rvalue void sunk double r3 matches rvalue 左...

函式過載 引用 內聯函式

預設引數 在定義或者宣告乙個函式的時候,給它的形參賦上乙個預設值,呼叫這個函式的時候,如果沒有把實參傳入,函式就會使用我們指定的預設引數,如果傳入實參,就會使用傳入的引數。預設引數可分為 全預設引數 在這個函式中,給所有的形參都指定了預設值。半預設引數 在這個函式中,只給一部分的形參指定了預設值。注...

預設引數 函式過載

預設引數 帶有初始值的引數 注 1.非全預設引數,引數的預設值賦值要從最後邊從右向左依次進行 eg int sum int a,int b 1,int c 2 2.實參的匹配是從左向右進行的 eg int sum int a,int b 1,int c 2 sum 10,20 10對應a,20對應b...