高質量程式設計 C 函式的高階特性

2021-05-23 23:34:39 字數 3327 閱讀 2963

void eatbeef(...);       // 可以改為     void eat(beef ...);

void eatfish(...); // 可以改為 void eat(fish ...);

void eatchicken(...); // 可以改為 void eat(chicken ...);

void function(void);

int function (void);

則可以判斷出function是第二個函式。問題是在c++/c程式中,我們可以忽略函式的返回值。在這種情況下,編譯器和程式設計師都不知道哪個function函式被呼叫。所以只能靠引數而不能靠返回值型別的不同來區分過載函式。編譯器根據引數為每個過載函式產生不同的內部識別符號。例如編譯器為示例8-1-1中的三個eat函式產生象_eat_beef、_eat_fish、_eat_chicken之類的內部識別符號(不同的編譯器可能產生不同風格的內部識別符號)。

該函式被c編譯器編譯後在庫中的名字為_foo,而c++編譯器則會產生像_foo_int_int之類的名字用來支援函式過載和型別安全連線。由於編譯後的名字不同,c++程式不能直接呼叫c函式。c++提供了乙個c連線交換指定符號extern「c」來解決這個問題。例如:

extern "c"

或者寫成

extern "c"

void print(...);     // 全域性函式

class a

# include void output( int x);    // 函式宣告

void output( float x); // 函式宣告

void output( int x)

void output( float x)

void main(void)

(1)相同的範圍(在同乙個類中);

(2)函式名字相同;

(3)引數不同;

(4)virtual關鍵字可有可無。

(1)不同的範圍(分別位於派生類與基類);

(2)函式名字相同;

(3)引數相同;

(4)基類函式必須有virtual關鍵字。

#include class base

void f(float x)

virtual void g(void)

};class derived : public base

};void main(void)

(1)如果派生類的函式與基類的函式同名,但是引數不同。此時,不論有無virtual關鍵字,基類的函式將被隱藏(注意別與過載混淆)。

(2)如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual關鍵字。此時,基類的函式被隱藏(注意別與覆蓋混淆)。

(1)函式derived::f(float)覆蓋了base::f(float)。

(2)函式derived::g(int)隱藏了base::g(float),而不是過載。

(3)函式derived::h(float)隱藏了base::h(float),而不是覆蓋。

#include class base

void g(float x)

void h(float x)};

class derived : public base

void g(int x)

void h(float x)

};

void main(void)

class base; 

class derived : public base

;void test(void)

示例8-2-3中,如果語句pd->f(10)一定要呼叫函式base::f(int),那麼將類derived修改為如下即可。

class derived : public base

};

}為什麼會這樣?我想是有兩個原因:一是函式的實現(定義)本來就與引數是否有預設值無關,所以沒有必要讓預設值出現在函式的定義體中。二是引數的預設值可能會改動,顯然修改函式的宣告比修改函式的定義要方便。

【規則8-3-2】如果函式有多個引數,引數只能從後向前挨個兒預設,否則將導致函式呼叫語句怪模怪樣。

錯誤的示例如下:

要注意,使用引數的預設值並沒有賦予函式新的功能,僅僅是使書寫變得簡潔一些。它可能會提高函式的易用性,但是也可能會降低函式的可理解性。所以我們只能適當地使用引數的預設值,要防止使用不當產生負面效果。示例8-3-2中,不合理地使用引數的預設值將導致過載函式output產生二義性。

#include void output( int x);

void output( int x, float y=0.0);

void output( int x)

void output( int x, float y)

void main(void)

運算子與普通函式在呼叫時的不同之處是:對於普通函式,引數出現在圓括號內;而對於運算子,引數出現在其左、右側。例如:

complex a, b, c;

...c = add(a, b); // 用普通函式

c = a + b; // 用運算子 +

(1)不要過分擔心自己不會用,它的本質仍然是程式設計師們熟悉的函式。

(2)不要過分熱心地使用,如果它不能使**變得更加易讀易寫,那就別用,否則會自找麻煩。

語句將被預處理器解釋為

由於運算子『+』比運算子『:』的優先順序高,所以上述語句並不等價於期望的

如果把巨集**改寫為

將被預處理器解釋為

對於c++ 而言,使用巨集**還有另一種缺點:無法操作類的私有資料成員。

inline void foo(int x, int y);     // inline僅與函式宣告放在一起

void foo(int x, int y)

void foo(int x, int y);     

inline void foo(int x, int y) // inline與函式定義體放在一起

class a

// 自動地成為內聯函式

}

// 標頭檔案

class a

// 定義檔案

inline void a::foo(int x, int y)

高質量C語言程式設計 函式

為什麼使用函式 函式呼叫即函式的使用。在程式中,是通過對函式的呼叫來執行函式體 的。函式呼叫是個 表示式 表示式的值即函式的返回值。函式呼叫的一般形式為 函式名 實參列表 實參可以是 表示式 函式定義絕不可巢狀。即函式定義中不可再定義函式 要保證 先定義 宣告 後呼叫 函式呼叫若出現在定義之前,就需...

C 高質量程式設計點滴

摘自 http www.sudu.cn info html edu c 20070103 236588.html 一 你需要乙個函式將乙個陣列賦值為等差數列,並將會在函式的外部使用他。不合理 int getarray int n return p 合理 void getarray int p,int...

高質量C 程式設計點滴

一 你需要乙個函式將乙個陣列賦值為等差數列,並將會在函式的外部使用它。不合理 int getarray int n return p 合理 void getarray int p,int n 解析 檢查記憶體洩露的最好辦法,就是檢查完全配對的申請和釋放,在函式中申請而在外部釋放,將導致 的一致性變差...