C++中的void類型

原文鏈接:https://www.cnblogs.com/zhoug2020/p/5416772.html

1.1. void類型

void類型其實是一種用於語法性的類型,而不是數據類型,主要用於作爲函數的參數或返回值,或者定義void指針,表示一種未知類型。

1.1.1. 作爲函數參數與返回值

void func( void );

void func( );

例如上面兩例,其實兩種聲明方式是等效的,在C++中如果參數列表爲空,默認的參數類型即爲void,但建議沒有參數時使用void以提高程序的可讀性。

因 爲C++在定義函數時不允許返回值類型爲空,在C++98之前,是允許定義函數時不定義返回值的,默認的返回值是int類型。其實默認int類型並不是好 事,如果函數有返回值在函數返回時是需要消耗CPU傳遞返回值的,也或許也是C++98標準將默認返回值類型改爲void的原因。

因爲C++不允許默認返回值,所以當函數不需要返回值是,需要將返回值類型聲明爲int類型。當調用返回值類型爲void類型的函數時,在工程上有很多實際代碼在前面加上(void)類型轉換,以提高代碼的可讀性。如調用上面定義的 func函數。

(void)func( );

從另一個角度講,這樣嚴謹的方式是可以提高軟件的健壯性的,調用函數時可以明確地看出是沒有返回值的,如果調用一個返回值不是int類型的函數時最好判斷其返回值,以檢查函數調用是否成功,如:

#include

char buff[5];

func( );

snprintf(buff, sizeof(buff), “%d”, “10240”);

顯 然這段代碼是有問題的,當然func沒有返回值,這樣調用是沒有問題,但snprintf的調用會有問題因爲緩衝區有可能太小而不能容納結果字符串,上面 的代碼就有這個問題。假設我們不知道snprintf有沒有返回值,可能這個BUG我們不會發現,直到有一天出現了我們不期望的結果。如果我們嚴格要求調 用每個函數時必須判斷函數的返回值,按照以下面的代碼編碼,就不會出給我們的程序造成隱患。

#include

#include

char buff[5];

(void)func( );

if( sizeof(buff) <= snprintf(buff, sizeof(buff), "%d", 10240) ){

buff[sizeof(buff) - 1] = '/0';

throw std::overflow_error("buff overflow");

}

1.1.2. void指針

void* pv = NULL;

string str = "string";

int i = 1;

pv = &str;

pv = &i;

int *pi = (int*)pv;

string* ps = (string*)pv;

如 上面的示例所示,void指針表示未知類型的指針,可以將任意類型的指針直接賦值給void指針,好比是C#、Java中的object引用,可以把任意 類型的對象賦值給它。但把void類型賦值給特定類型的指針時,就需要進行強制轉換,因爲C++爲類型語言,儘可能保證類型安全,如果使用了強制類型轉 換,編譯器就認爲程序員知道他(她)在幹什麼,程序也應該負起這樣做的責任。

值得注意的是,函數指針與類成員的指針不能賦值給void*類型變量。

void* 在C語言中一般用於動態內存的操作,因爲malloc和calloc返回的類型都是void*類型。在W3C的協議庫libwww裏,大量使用了 void*類型,如果使用C++的繼承特性的話,應該會使代碼可讀性更好。而在C++中則可以使用new返回特定類型指針,更不容易出現問題,所以 void*的作用顯得更弱了。

void*在C++中的主要作用就是作爲函數指針的返回值[C++ Programming Language],例如:

void* my_alloc(size_t size);

void* 還用於一些底層的操作,例如我們有兩個類UdpSocket和TcpSocket,在我們一個傳輸類中需要支持兩種協議,提供統一的接口,但 UdpSocket和TcpSocket之間沒有繼承關係,無法使用共同的基類指針,而只能使用void*指針,代碼如[??]。

class UdpSocket{};

class TcpSocket{};

class Transfer

{

public:

enum Protocol { UDP, TCP };

Transfer(Protocol prot) : _prot(prot)

{

if( _prot == UDP)

_sock = new UdpSocket( );

else if( _prot == TCP )

_sock = new TcpSocket( );

else

throw std::invalid_argument("prot");

}

~Transfer( void )

{

if(_prot == UDP)

delete (UdpSocket*)_sock;

else

delete (TcpSocket*)_sock;

_sock = NULL;

}

private:

void* _sock;

Protocol _prot;

};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章