第一課 C過渡到C 之二

2021-07-25 13:20:43 字數 3947 閱讀 7615

c++的函式過載機制為我們程式設計師提供了很大的便利,但同時也會帶來一些問題,這時我們會發現,當我們呼叫過載函式時,會出現編譯不通過的現象,還有給別人提夠函式介面也會出現一些問題。

#include "stdafx.h"

#include

// 以輸出不同型別的引數為例的過載函式

void myprintf(char c)

void myprintf(int i)

int main()

居然可以編譯通過,並將正確答案顯示出來,是不是太神奇了???

然而細心的朋友會發現,我們並沒有過載short的函式,而為什麼能夠正確編譯和輸出呢?這是因為進行了提公升匹配,short型別自動提公升到了int型別,所以程式能夠成功編譯和執行。

但是過載有些時候還是會出問題的比如下面的例子:

#include "stdafx.h"

#include

// 以輸出不同型別的引數為例的過載函式

void myprintf(char c)

void myprintf(int i)

void myprintf(float f)

int main()

此時的myprintf(ui);就會編譯不通過,會提示下面的資訊:

從這個錯誤提示上可以看出,我們呼叫unsigned int型別的變數時,它可以有多重呼叫方式,這樣就會使得編譯器很困惑,所以就會導致編譯錯誤。那麼怎樣才能修改這樣的**,使它能夠通過編譯呢?很簡單的一種就是再增加乙個unsigned int型別的過載函式,**如下:

#include "stdafx.h"

#include

// 以輸出不同型別的引數為例的過載函式

void myprintf(char c)

void myprintf(int i)

void myprintf(float f)

void myprintf(unsigned

int ui)

int main()

這樣就能夠很順利的通過編譯,但是我們應該如何去寫過載函式呢?究竟寫多少個過載函式才好呢?這個應該看具體專案需求,需要寫幾個就寫幾個,並不是說過載函式寫得越多越好,因為多了也沒用。

過載函式的匹配規則:

1.精準匹配,比如 int -> int

2.提公升匹配,比如 char -> int -> double

3.型別轉換匹配,int -> unsigned int

所以當過載函式的匹配規則發生衝突或者有多個匹配函式時,就會出現二義性。定義太多或太少的過載函式時容易出現問題

請看這樣指標過載的例子

#include "stdafx.h"

#include

// 以輸出不同型別的引數為例的過載函式

void myprintf(char *str)

void myprintf(int *pi)

int main()

此時的過載和呼叫都沒有問題,可以編譯通過和正確執行,但是如果我有乙個萬能指標void*的變數時,程式又會出現什麼情況呢?

還是先看**吧

#include "stdafx.h"

#include

// 以輸出不同型別的引數為例的過載函式

void myprintf(char *str)

void myprintf(int *pi)

int main()

上面的**在編譯時,就會出現問題。編譯的錯誤提示資訊如下:

為什麼會出現這樣的錯誤呢?原因很簡單,因為void*的變數是萬能指標嘛,它可以轉換成任意的指標的型別,所以此時就會出現二義性,編譯器也不知道該呼叫哪個函式了。

c++的特性中,有乙個預設引數的特性,就是我們可以給函式引數預設的賦值,**如下:

#include "stdafx.h"

#include

// 以輸出不同型別的引數為例的過載函式

void myprintf(char c, bool bline = false)

int main()

首先,肯定一點是上面的**沒有錯誤,它的輸出結果是:

從輸出結果上可以看出,當我們給它傳遞乙個true引數時,就表示有換行,而不傳遞引數,那麼它就會使用預設引數false,這和我們顯示的傳遞false的效果是一樣的。

需要注意的時,預設引數還是有條件的,比如預設引數必須要從右到左賦值預設引數,不允許有預設值的引數右邊是沒有預設值的引數。

比如:

#include "stdafx.h"

#include

// 以輸出不同型別的引數為例的過載函式

void myprintf(char c, bool bline = false, int i)

int main()

此時,我們就是不呼叫這個函式,它也不會編譯通過,其實這也沒有什麼好解釋的,記住就可以了。

內聯函式的寫法很簡單,直接在函式名前直接加上inline關鍵字就可以了,**如下:

#include "stdafx.h"

#include

// 以輸出不同型別的引數為例的過載函式

inline

void myprintf(char c, bool bline = false)

int main()

從**上可以看出,內聯函式的使用和普通函式一樣,沒有任何的差別。

內聯函式的好處

內聯函式不會新建棧,而是直接將**展開,這樣就會大大的提高了函式的執行效率,因為減少了建立棧,銷毀棧的過程。需要注意的是,內聯函式只是針對棧空間來說的,比如說在堆空間申請的記憶體和釋放跟內聯是沒有關係的。只有在棧空間上執行的函式才有可能被內聯。

內聯函式既然有好處,肯定也有它的缺點

內聯函式的缺點是,它會造成**的膨脹,使生成的可執行程式變得龐大。

內聯函式的作用

inline關鍵字只是告訴編譯器這個函式要內聯,但是具體能不能成功的內聯,是由編譯器來決定。具體的規則也不太好說清,據聽說是內聯的規則是經常變化的,所以也沒有乙個固定的準則。但是大概有一些規則,只能說是一般性的規則。

通常情況下判定標準:

1.**量很龐大

2.不加inline,他不會變成內聯函式,但是加上的話,也不一定內聯

內聯和巨集定義的區別

內聯函式和巨集定義都是直接展開,那它們之間有什麼區別呢?

巨集定義是赤裸裸的替換,不帶半點兒的修飾,沒有一點兒型別檢測;

內聯函式,它畢竟還是函式,所以它有型別檢測;

c++的型別轉換與c語言的型別轉換不同,c語言的型別轉換都是強制轉換的。而c++中有四中型別轉換,只有一種型別轉換等同於c語言的強制型別轉換,其它的三種轉換都不是強制轉換。他們分別是:

1.static_cast它不是強制轉換,只是簡單的轉換,是c++的轉換風格

2.const_cast表示去常量操作,但是它還是不能真正的去掉引數的常量,我們可以認為只是矇騙編譯器通過編譯,沒有其他的作用了。

3.dynamic_cast主要用於類層次間的上行轉換和下行轉換,還可以用於類之間的交叉轉換

4.reinterpret_cast此識別符號的意思即為資料的二進位制形式重新解釋,但是不改變其值

我們先了解這幾種轉換關係,以後再做深入的解釋和說明。

C語言第一課

一 c基礎 進製的轉換 進製,進製機制 常見的有二進位制 八進位制 十進位制 十六進製制 例 二進位制 0101010 八進位制 0235 十進位制 9 十六進製制 0x8a 注 十六進製制後面的10 16由a,b,c,d,e,f代替 進製的區分 八進位制前面會加 0 十六進製制後面會加 0x 進製...

c的第一課

一 前言 一切,都想從不一樣做起。大學,原以為會和我當時高中想象的那樣,可以談場轟轟烈烈的戀愛,可以自由自在的旅行,可以忘乎所以,盡己之所興。如今,大三結束。驀然回首,卻發現自己浪費了那麼多改變自己的機會。如今,大學只剩最後一年,我要用這最後的時間去彌補曾經所浪費的一切,從現在開始,朝著自己的目標勇...

C語言第一課

開始的第乙個程式是乙個最簡單的程式,也就是最經典的hello world程式,它的功能為列印出hello world。程式的內容非常簡單,也是c語言編寫程式的基本結構框架。機構的電腦是基於虛擬機器的,其程式設計是gcc的。1.建立hello.c檔案 vim hello.c2.編寫hello worl...