深刻C++ typedef的用法總結(必看)。本站提示廣大學習愛好者:(深刻C++ typedef的用法總結(必看))文章只能為提供參考,不一定能成為您想要的結果。以下是深刻C++ typedef的用法總結(必看)正文
第1、四個用處
用處一:
界說一品種型的別號,而不只是簡略的宏調換。可以用作同時聲明指針型的多個對象。好比:
char* pa, pb; // 這多半不相符我們的意圖,它只聲清楚明了一個指向字符變量的指針,
// 和一個字符變量;
以下則可行:
typedef char* PCHAR; // 普通用年夜寫
PCHAR pa, pb; // 可行,同時聲清楚明了兩個指向字符變量的指針
固然:
char *pa, *pb;
也可行,但絕對來講沒有效typedef的情勢直不雅,特別在須要年夜量指針的處所,typedef的方法更省事。
用處二:
用在舊的C的代碼中(詳細多舊沒有查),贊助struct。之前的代碼中,聲明struct新對象時,必需要帶上struct,即情勢為: struct 構造名 對象名,如:
struct tagPOINT1
{
int x;
int y;
};
struct tagPOINT1 p1;
而在C++中,則可以直接寫:構造名 對象名,即:
tagPOINT1 p1;
估量或人認為常常多寫一個struct太費事了,因而就創造了:
typedef struct tagPOINT
{
int x;
int y;
}POINT;
POINT p1; // 如許就比本來的方法少寫了一個struct,比擬省事,特別在年夜量應用的時刻
也許,在C++中,typedef的這類用處二不是很年夜,然則懂得了它,對控制之前的舊代碼照樣有贊助的,究竟我們在項目中有能夠會碰到較早些年月遺留上去的代碼。
用處三:
用typedef來界說與平台有關的類型。
好比界說一個叫 REAL 的浮點類型,在目的平台一上,讓它表現最高精度的類型為:
typedef long double REAL;
在不支撐 long double 的平台二上,改成:
typedef double REAL;
在連 double 都不支撐的平台三上,改成:
typedef float REAL;
也就是說,當跨平台時,只需改下 typedef 自己就行,不消對其他源碼做任何修正。
尺度庫就普遍應用了這個技能,好比size_t。
別的,由於typedef是界說了一品種型的新別號,不是簡略的字符串調換,所以它比宏來得穩健(固然用宏有時也能夠完成以上的用處)。
用處四:
為龐雜的聲明界說一個新的簡略的別號。辦法是:在本來的聲明裡慢慢用別號調換一部門龐雜聲明,如斯輪回,把帶變量名的部門留到最初調換,獲得的就是原聲明的最簡化版。舉例:
1. 原聲明:int *(*a[5])(int, char*);
變量名為a,直接用一個新別號pFun調換a便可以了:
typedef int *(*pFun)(int, char*);
原聲明的最簡化版:
pFun a[5];
2. 原聲明:void (*b[10]) (void (*)());
變量名為b,先調換左邊部門括號裡的,pFunParam為別號一:
typedef void (*pFunParam)();
再調換右邊的變量b,pFunx為別號二:
typedef void (*pFunx)(pFunParam);
原聲明的最簡化版:
pFunx b[10];
3. 原聲明:doube(*)() (*e)[9];
變量名為e,先調換右邊部門,pFuny為別號一:
typedef double(*pFuny)();
再調換左邊的變量e,pFunParamy為別號二
typedef pFuny (*pFunParamy)[9];
原聲明的最簡化版:
pFunParamy e;
懂得龐雜聲明可用的“右左軌則”:
從變量名看起,先往右,再往左,碰著一個圓括號就調轉浏覽的偏向;括號內剖析完就跳出括號,照樣按先右後左的次序,如斯輪回,直到全部聲明剖析完。舉例:
int (*func)(int *p);
起首找到變量名func,裡面有一對圓括號,並且右邊是一個*號,這解釋func是一個指針;然後跳出這個圓括號,先看左邊,又碰到圓括號,這解釋(*func)是一個函數,所以func是一個指向這類函數的指針,即函數指針,這類函數具有int*類型的形參,前往值類型是int。
int (*func[5])(int *);
func左邊是一個[]運算符,解釋func是具有5個元素的數組;func的右邊有一個*,解釋func的元素是指針(留意這裡的*不是潤飾func,而是潤飾func[5]的,緣由是[]運算符優先級比*高,func先跟[]聯合)。跳出這個括號,看左邊,又碰到圓括號,解釋func數組的元素是函數類型的指針,它指向的函數具有int*類型的形參,前往值類型為int。
也能夠記住2個形式:
type (*)(....)函數指針
type (*)[]數組指針
第2、兩年夜圈套
圈套一:
記住,typedef是界說了一品種型的新別號,分歧於宏,它不是簡略的字符串調換。好比:
先界說:
typedef char* PSTR;
然後:
int mystrcmp(const PSTR, const PSTR);
const PSTR現實上相當於const char*嗎?不是的,它現實上相當於char* const。
緣由在於const賜與了全部指針自己以常量性,也就是構成了常量指針char* const。
簡略來講,記住當const和typedef一路湧現時,typedef不會是簡略的字符串調換就行。
圈套二:
typedef在語法上是一個存儲類的症結字(如auto、extern、mutable、static、register等一樣),固然它其實不真正影響對象的存儲特征,如:
typedef static int INT2; //弗成行
編譯將掉敗,會提醒“指定了一個以上的存儲類”。
第3、typedef 與 #define的差別
案例一:
平日講,typedef要比#define要好,特殊是在有指針的場所。請看例子:
typedef char *pStr1;
#define pStr2 char *;
pStr1 s1, s2;
pStr2 s3, s4;
在上述的變量界說中,s1、s2、s3都被界說為char *,而s4則界說成了char,不是我們所預期的指針變量,基本緣由就在於#define只是簡略的字符串調換而typedef則是為一個類型起新名字。
案例二:
上面的代碼中編譯器會報一個毛病,你曉得是哪一個語句錯了嗎?
typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;
是p2++失足了。這個成績再一次提示我們:typedef和#define分歧,它不是簡略的文本調換。上述代碼中const pStr p2其實不等於const char * p2。const pStr p2和const long x實質上沒有差別,都是對變量停止只讀限制,只不外此處變量p2的數據類型是我們本身界說的而不是體系固有類型罷了。是以,const pStr p2的寄義是:限制數據類型為char *的變量p2為只讀,是以p2++毛病。
第四部門材料:應用 typedef 克制劣質代碼
摘要:Typedef 聲明有助於創立平台有關類型,乃至能隱蔽龐雜和難以懂得的語法。不論如何,應用 typedef 能為代碼帶來意想不到的利益,經由過程本文你可以進修用 typedef 防止缺欠,從而使代碼更硬朗。
typedef 聲明,簡稱 typedef,為現有類型創立一個新的名字。好比人們經常應用 typedef 來編寫更雅觀和可讀的代碼。所謂雅觀,意指 typedef 能隱蔽愚笨的語法結構和平台相干的數據類型,從而加強可移植性和和將來的可保護性。本文上面將養精蓄銳來提醒 typedef 壯大功效和若何防止一些罕見的圈套。
Q:若何創立平台有關的數據類型,隱蔽愚笨且難以懂得的語法?
A: 應用 typedefs 為現有類型創立同義字。
界說易於記憶的類型名
typedef 應用最多的處所是創立易於記憶的類型名,用它來歸檔法式員的意圖。類型湧現在所聲明的變量名字中,位於 ''typedef'' 症結字左邊。例如:
typedef int size;此聲明界說了一個 int 的同義字,名字為 size。留意 typedef 其實不創立新的類型。它僅僅為現有類型添加一個同義字。你可以在任何須要 int 的高低文中應用 size:
void measure(size * psz); size array[4];size len = file.getlength();std::vector <size> vs; typedef 還可以掩蓋相符類型,如指針和數組。例如,你不消象上面如許反復界說有 81 個字符元素的數組:
char line[81];char text[81];界說一個 typedef,每當要用到雷同類型和年夜小的數組時,可以如許:
typedef char Line[81]; Line text, secondline;getline(text);異樣,可以象上面如許隱蔽指針語法:
typedef char * pstr;int mystrcmp(pstr, pstr);這裡將帶我們達到第一個 typedef 圈套。尺度函數 strcmp()有兩個‘const char *'類型的參數。是以,它能夠會誤導人們象上面如許聲明 mystrcmp():
int mystrcmp(const pstr, const pstr); 這是毛病的,依照次序,‘const pstr'被說明為‘char * const'(一個指向 char 的常量指針),而不是‘const char *'(指向常量 char 的指針)。這個成績很輕易處理:
typedef const char * cpstr; int mystrcmp(cpstr, cpstr); // 如今是准確的記住:不論甚麼時刻,只需為指針聲明 typedef,那末都要在終究的 typedef 稱號中加一個 const,以使得該指針自己是常量,而不是對象。
代碼簡化
下面評論辯論的 typedef 行動有點像 #define 宏,用其現實類型替換同義字。分歧點是 typedef 在編譯時被說明,是以讓編譯器來敷衍超出預處置器才能的文本調換。例如:
typedef int (*PF) (const char *, const char *);這個聲明引入了 PF 類型作為函數指針的同義字,該函數有兩個 const char * 類型的參數和一個 int 類型的前往值。假如要應用以下情勢的函數聲明,那末上述這個 typedef 是弗成或缺的:
PF Register(PF pf);Register() 的參數是一個 PF 類型的回調函數,前往某個函數的地址,其簽名與先前注冊的名字雷同。做一次深呼吸。上面我展現一下假如不消 typedef,我們是若何完成這個聲明的:
int (*Register (int (*pf)(const char *, const char *))) (const char *, const char *); 很少有法式員懂得它是甚麼意思,更不消說這類隱晦的代碼所帶來的失足風險了。明顯,這裡應用 typedef 不是一種特權,而是一種必須。持疑惑立場的人能夠會問:“OK,有人還會寫如許的代碼嗎?”,疾速閱讀一下提醒 signal()函數的頭文件 <csinal>,一個有異樣接口的函數。
typedef 和存儲類症結字(storage class specifier)
這類說法是否是有點使人驚奇,typedef 就像 auto,extern,mutable,static,和 register 一樣,是一個存儲類症結字。這並是說 typedef 會真正影響對象的存儲特征;它只是說在語句組成上,typedef 聲明看起來象 static,extern 等類型的變量聲明。上面將帶到第二個圈套:
typedef register int FAST_COUNTER; // 毛病編譯通不外。成績出在你不克不及在聲明中有多個存儲類症結字。由於符號 typedef 曾經占領了存儲類症結字的地位,在 typedef 聲明中不克不及用 register(或任何其它存儲類症結字)。
增進跨平台開辟
typedef 有別的一個主要的用處,那就是界說機械有關的類型,例如,你可以界說一個叫 REAL 的浮點類型,在目的機械上它可以i取得最高的精度:
typedef long double REAL; 在不支撐 long double 的機械上,該 typedef 看起來會是上面如許:
typedef double REAL; 而且,在連 double 都不支撐的機械上,該 typedef 看起來會是如許: 、
typedef float REAL; 你不消對源代碼做任何修正,即可以在每種平台上編譯這個應用 REAL 類型的運用法式。獨一要改的是 typedef 自己。在年夜多半情形下,乃至這個渺小的更改完整都可以經由過程奧妙的前提編譯來主動完成。不是嗎? 尺度庫普遍地應用 typedef 來創立如許的平台有關類型:size_t,ptrdiff 和 fpos_t 就是個中的例子。另外,象 std::string 和 std::ofstream 如許的 typedef 還隱蔽了長長的,難以懂得的模板特化語法,例如:basic_string<char, char_traits<char>,allocator<char>> 和 basic_ofstream<char, char_traits<char>>。