不卡AV在线|网页在线观看无码高清|亚洲国产亚洲国产|国产伦精品一区二区三区免费视频

學(xué)習(xí)啦>學(xué)習(xí)英語(yǔ)>英語(yǔ)其它>

c++中是什么意思

時(shí)間: 玉蓮928 分享

  ->在C++中是什么意思?下面是學(xué)習(xí)啦小編給大家整理的c++中是什么意思,供大家參閱!

  ->在C++中是什么意思

  -> 在c++中為取成員運(yùn)算符

  對(duì)象指針/結(jié)構(gòu)指針->成員變量/成員函數(shù)

  該運(yùn)算符的作用,取得指針?biāo)赶虻念悓?duì)象或結(jié)構(gòu)變量的成員變量的值,或者調(diào)用其成員函數(shù)。

  例如:

  int *p;

  struct student

  { char name[20];

  int num;

  }stu;

  stu={xiaoming,90};

  p=&stu;

  cout<<stu.name<<stu.num<<endl;

  cout<<p->name<<p->num<<endl;

  這兩個(gè)cout的效果是一樣的

  ::在c++中的表示含義

  ::在c++中表示作用域,和所屬關(guān)系

  比如

  class A

  {

  public:

  int test();

  }

  int A::test()//表示test是屬于A的

  {

  return 0;

  }

  類似的還有其他,就不列舉了

  --------------------

  比如

  int a;

  void test ()

  {

  int a = ::a;//用全局變量a,給本地變量a賦值

  c++中的宏使用

  眾多C++書籍都忠告我們C語(yǔ)言宏是萬(wàn)惡之首,但事情總不如我們想象的那么壞,就如同goto一樣。宏有

  一個(gè)很大的作用,就是自動(dòng)為我們產(chǎn)生代碼。如果說(shuō)模板可以為我們產(chǎn)生各種型別的代碼(型別替換),

  那么宏其實(shí)可以為我們?cè)诜?hào)上產(chǎn)生新的代碼(即符號(hào)替換、增加)。

  關(guān)于宏的一些語(yǔ)法問(wèn)題,可以在google上找到。相信我,你對(duì)于宏的了解絕對(duì)沒(méi)你想象的那么多。如果你

  還不知道#和##,也不知道prescan,那么你肯定對(duì)宏的了解不夠。

  我稍微講解下宏的一些語(yǔ)法問(wèn)題(說(shuō)語(yǔ)法問(wèn)題似乎不妥,macro只與preprocessor有關(guān),跟語(yǔ)義分析又無(wú)關(guān)):

  1. 宏可以像函數(shù)一樣被定義,例如:

  #define min(x,y) (x<y?x:y) //事實(shí)上這個(gè)宏存在BUG

  但是在實(shí)際使用時(shí),只有當(dāng)寫上min(),必須加括號(hào),min才會(huì)被作為宏展開(kāi),否則不做任何處理。

  2. 如果宏需要參數(shù),你可以不傳,編譯器會(huì)給你警告(宏參數(shù)不夠),但是這會(huì)導(dǎo)致錯(cuò)誤。如C++書籍中所描

  述的,編譯器(預(yù)處理器)對(duì)宏的語(yǔ)法檢查不夠,所以更多的檢查性工作得你自己來(lái)做。

  3. 很多程序員不知道的#和##

  #符號(hào)把一個(gè)符號(hào)直接轉(zhuǎn)換為字符串,例如:

  #define STRING(x) #x

  const char *str = STRING( test_string ); str的內(nèi)容就是"test_string",也就是說(shuō)#會(huì)把其后的符號(hào)

  直接加上雙引號(hào)。

  ##符號(hào)會(huì)連接兩個(gè)符號(hào),從而產(chǎn)生新的符號(hào)(詞法層次),例如:

  #define SIGN( x ) INT_##x

  int SIGN( 1 ); 宏被展開(kāi)后將成為:int INT_1;

  4. 變參宏,這個(gè)比較酷,它使得你可以定義類似的宏:

  #define LOG( format, ... ) printf( format, __VA_ARGS__ )

  LOG( "%s %d", str, count );

  __VA_ARGS__是系統(tǒng)預(yù)定義宏,被自動(dòng)替換為參數(shù)列表。

  5. 當(dāng)一個(gè)宏自己調(diào)用自己時(shí),會(huì)發(fā)生什么?例如:

  #define TEST( x ) ( x + TEST( x ) )

  TEST( 1 ); 會(huì)發(fā)生什么?為了防止無(wú)限制遞歸展開(kāi),語(yǔ)法規(guī)定,當(dāng)一個(gè)宏遇到自己時(shí),就停止展開(kāi),也就是

  說(shuō),當(dāng)對(duì)TEST( 1 )進(jìn)行展開(kāi)時(shí),展開(kāi)過(guò)程中又發(fā)現(xiàn)了一個(gè)TEST,那么就將這個(gè)TEST當(dāng)作一般的符號(hào)。TEST(1)

  最終被展開(kāi)為:1 + TEST( 1) 。

  6. 宏參數(shù)的prescan,

  當(dāng)一個(gè)宏參數(shù)被放進(jìn)宏體時(shí),這個(gè)宏參數(shù)會(huì)首先被全部展開(kāi)(有例外,見(jiàn)下文)。當(dāng)展開(kāi)后的宏參數(shù)被放進(jìn)宏體時(shí),

  預(yù)處理器對(duì)新展開(kāi)的宏體進(jìn)行第二次掃描,并繼續(xù)展開(kāi)。例如:

  #define PARAM( x ) x

  #define ADDPARAM( x ) INT_##x

  PARAM( ADDPARAM( 1 ) );

  因?yàn)锳DDPARAM( 1 ) 是作為PARAM的宏參數(shù),所以先將ADDPARAM( 1 )展開(kāi)為INT_1,然后再將INT_1放進(jìn)PARAM。

  例外情況是,如果PARAM宏里對(duì)宏參數(shù)使用了#或##,那么宏參數(shù)不會(huì)被展開(kāi):

  #define PARAM( x ) #x

  #define ADDPARAM( x ) INT_##x

  PARAM( ADDPARAM( 1 ) ); 將被展開(kāi)為"ADDPARAM( 1 )"。

  使用這么一個(gè)規(guī)則,可以創(chuàng)建一個(gè)很有趣的技術(shù):打印出一個(gè)宏被展開(kāi)后的樣子,這樣可以方便你分析代碼:

  #define TO_STRING( x ) TO_STRING1( x )

  #define TO_STRING1( x ) #x

  TO_STRING首先會(huì)將x全部展開(kāi)(如果x也是一個(gè)宏的話),然后再傳給TO_STRING1轉(zhuǎn)換為字符串,現(xiàn)在你可以這樣:

  const char *str = TO_STRING( PARAM( ADDPARAM( 1 ) ) );去一探PARAM展開(kāi)后的樣子。

  7. 一個(gè)很重要的補(bǔ)充:就像我在第一點(diǎn)說(shuō)的那樣,如果一個(gè)像函數(shù)的宏在使用時(shí)沒(méi)有出現(xiàn)括號(hào),那么預(yù)處理器只是

  將這個(gè)宏作為一般的符號(hào)處理(那就是不處理)。

  我們來(lái)見(jiàn)識(shí)一下宏是如何幫助我們自動(dòng)產(chǎn)生代碼的。如我所說(shuō),宏是在符號(hào)層次產(chǎn)生代碼。我在分析Boost.Function

  模塊時(shí),因?yàn)樗褂昧舜罅康暮?宏嵌套,再嵌套),導(dǎo)致我壓根沒(méi)看明白代碼。后來(lái)發(fā)現(xiàn)了一個(gè)小型的模板庫(kù)ttl,說(shuō)的

  是開(kāi)發(fā)一些小型組件去取代部分Boost(這是一個(gè)好理由,因?yàn)锽oost確實(shí)太大)。同樣,這個(gè)庫(kù)也包含了一個(gè)function庫(kù)。

  這里的function也就是我之前提到的functor。ttl.function庫(kù)里為了自動(dòng)產(chǎn)生很多類似的代碼,使用了一個(gè)宏:

  #define TTL_FUNC_BUILD_FUNCTOR_CALLER(n) /

  template< typename R, TTL_TPARAMS(n) > /

  struct functor_caller_base##n /

  ///...

  該宏的最終目的是:通過(guò)類似于TTL_FUNC_BUILD_FUNCTOR_CALLER(1)的調(diào)用方式,自動(dòng)產(chǎn)生很多functor_caller_base模板:

  template <typename R, typename T1> struct functor_caller_base1

  template <typename R, typename T1, typename T2> struct functor_caller_base2

  template <typename R, typename T1, typename T2, typename T3> struct functor_caller_base3

  ///...

  那么,核心部分在于TTL_TPARAMS(n)這個(gè)宏,可以看出這個(gè)宏最終產(chǎn)生的是:

  typename T1

  typename T1, typename T2

  typename T1, typename T2, typename T3

  ///...

  我們不妨分析TTL_TPARAMS(n)的整個(gè)過(guò)程。分析宏主要把握我以上提到的一些要點(diǎn)即可。以下過(guò)程我建議你翻著ttl的代碼,

  相關(guān)代碼文件:function.hpp, macro_params.hpp, macro_repeat.hpp, macro_misc.hpp, macro_counter.hpp。

  so, here we Go

  分析過(guò)程,逐層分析,逐層展開(kāi),例如TTL_TPARAMS(1):

  #define TTL_TPARAMS(n) TTL_TPARAMSX(n,T)

  => TTL_TPARAMSX( 1, T )

  #define TTL_TPARAMSX(n,t) TTL_REPEAT(n, TTL_TPARAM, TTL_TPARAM_END, t)

  => TTL_REPEAT( 1, TTL_TPARAM, TTL_TPARAM_END, T )

  #define TTL_TPARAM(n,t) typename t##n,

  #define TTL_TPARAM_END(n,t) typename t##n

  #define TTL_REPEAT(n, m, l, p) TTL_APPEND(TTL_REPEAT_, TTL_DEC(n))(m,l,p) TTL_APPEND(TTL_LAST_REPEAT_,n)(l,p)

  注意,TTL_TPARAM, TTL_TPARAM_END雖然也是兩個(gè)宏,他們被作為TTL_REPEAT宏的參數(shù),按照prescan規(guī)則,似乎應(yīng)該先將

  這兩個(gè)宏展開(kāi)再傳給TTL_REPEAT。但是,如同我在前面重點(diǎn)提到的,這兩個(gè)宏是function-like macro,使用時(shí)需要加括號(hào),

  如果沒(méi)加括號(hào),則不當(dāng)作宏處理。因此,展開(kāi)TTL_REPEAT時(shí),應(yīng)該為:

  => TTL_APPEND( TTL_REPEAT_, TTL_DEC(1))(TTL_TPARAM,TTL_TPARAM_END,T) TTL_APPEND( TTL_LAST_REPEAT_,1)(

  TTL_TPARAM_END,T)

  這個(gè)宏體看起來(lái)很復(fù)雜,仔細(xì)分析下,可以分為兩部分:

  TTL_APPEND( TTL_REPEAT_, TTL_DEC(1))(TTL_TPARAM,TTL_TPARAM_END,T)以及

  TTL_APPEND( TTL_LAST_REPEAT_,1)(TTL_TPARAM_END,T)

  先分析第一部分:

  #define TTL_APPEND( x, y ) TTL_APPEND1(x,y) //先展開(kāi)x,y再將x,y連接起來(lái)

  #define TTL_APPEND1( x, y ) x ## y

  #define TTL_DEC(n) TTL_APPEND(TTL_CNTDEC_, n)

  根據(jù)先展開(kāi)參數(shù)的原則,會(huì)先展開(kāi)TTL_DEC(1)

  => TTL_APPEND(TTL_CNTDEC_,1) => TTL_CNTDEC_1

  #define TTL_CNTDEC_1 0 注意,TTL_CNTDEC_不是宏,TTL_CNTDEC_1是一個(gè)宏。

  => 0 , 也就是說(shuō),TTL_DEC(1)最終被展開(kāi)為0?;氐絋TL_APPEND部分:

  => TTL_REPEAT_0 (TTL_TPARAM,TTL_TPARAM_END,T)

  #define TTL_REPEAT_0(m,l,p)

  TTL_REPEAT_0這個(gè)宏為空,那么,上面說(shuō)的第一部分被忽略,現(xiàn)在只剩下第二部分:

  TTL_APPEND( TTL_LAST_REPEAT_,1)(TTL_TPARAM_END,T)

  => TTL_LAST_REPEAT_1 (TTL_TPARAM_END,T) // TTL_APPEND將TTL_LAST_REPEAT_和1合并起來(lái)

  #define TTL_LAST_REPEAT_1(m,p) m(1,p)

  => TTL_TPARAM_END( 1, T )

  #define TTL_TPARAM_END(n,t) typename t##n

  => typename T1 展開(kāi)完畢。

  雖然我們分析出來(lái)了,但是這其實(shí)并不是我們想要的。我們應(yīng)該從那些宏里去獲取作者關(guān)于宏的編程思想。很好地使用宏

  看上去似乎是一些偏門的奇技淫巧,但是他確實(shí)可以讓我們編碼更自動(dòng)化。

  

看過(guò)c++中是什么意思的人還看了:

1.關(guān)于c++的面試題

2.c中bool的用法

3.java基礎(chǔ)知識(shí)java是一門面向?qū)ο缶幊陶Z(yǔ)言,不...

4.java實(shí)習(xí)心得感悟

2674039