c++物件模型筆記:struct 和 class

來源:互聯網
上載者:User
在c++裡面,struct 和 class 有沒有區別?

有的!但是僅有一個,那就是struct的成員訪問的預設許可權是public,而class則是private的。

比如:

  1. class A
  2. {//a,b是private成員
  3.     int a;
  4.     int b;
  5. };

  6. struct B
  7. {//c,d是public成員
  8.    int c;
  9.    int d;
  10. };

就這一個區別而已!

那麼,為什麼還要保留這個struct呢,理由就是為了和C語言相容~,如果不是為了這個理由,c++中有很多東西都可以大量的簡化。

如果在聲明和定義時候使用不同的關鍵字,會產生什麼呢?比如:

  1. class A
  2. {//定義時候用class
  3. public:
  4.     int a;
  5. };

  6. struct A aA; //使用時候用struct,注意,成員的預設訪問屬性是在定義中決定的,不是在聲明中!
  7. aA.a = 1;

在不同的編譯器可能會有不同的行為----在vs2005中,會產生一個警告;而在g++中什麼都沒有發生;

不過警告多了,畢竟還是不好的,尤其是在一大堆警告裡面含有幾個錯誤的情況(以前做項目時候這種情況出現,我簡直想打人....一百多個警告裡面,才有4個錯誤,當然,可以屏蔽警告,不過最好還是不要那麼做,否則,運行時出現問題了,你就要頭痛了,因為某些警告就是含蓄的告訴你一些執行階段錯誤的資訊,相信警告,他是你的朋友~)

那麼在C++中,什麼時候用struct呢?Lippman的答案是:在你想要的時候;就是說從編譯器的角度,兩者並沒有本質的區別,但是在使用者的習慣用法來看,可能會有微妙的區別----畢竟,一看到struct就可以想到這是C的東西,也就是如果是用C++的物件導向的東東來編程,用class可能會好一些;如果編寫的東西沒有用到物件導向的東西(比如封裝,繼承,多態),那就用struct吧。

當然有些公司的編程規範裡面也會有這方面的說明,具體問題還得具體分析,呵呵。

還有一個相關的話題,那就是有些在C語言中常用的技巧到了C++可能會變成陷阱。下舉兩個例子。

1、在C語言中,下面這個技巧是常用的:可變大小的數組,可以通過結尾僅含一個元素的char數組的結構體來實現(這說的都是什麼啊?舉個例子吧)比如,有如下代碼:

  1. struct A
  2. {
  3.     int totalSize;  //總的實際長度
  4.     ...   //其他成員
  5.     char str[1];  //可變長的字串
  6. };
  7. char str[] = "abcdefg";
  8. struct A *pa = (struct A*) malloc( sizeof(struct A) * strlen(str) );
  9. pa->totalSize = sizeof(struct A) * strlen(str);
  10. strcpy(& pa->str, str);
  11. ...

其過程只可意會,不可言傳,呵呵(尷尬中,因為不知道怎麼表達)

那麼這樣做和通過指標作為成員的方法有什麼好處呢?該方法如下:

  1. struct A
  2. {
  3.    int stringSize;
  4.    char *pStr;
  5. };
  6. char str[] = "abcdefg";
  7. struct A *pa = (struct A*)malloc( sizeof(struct A) );

  8. pa->pStr = (char*)malloc( strlen(str) + 1);

  9. strcpy(pa->pStr, str);

  10. pa->stringSize = strlen(pa->pStr);

第一種做法的好處有二:一是struct A的成員char str佔了1個位元組,而第二種方法的指標佔了4個位元組;二是第一種方法訪問的時候夠直接,第二種方法訪問時候就多了一個間接關係(通過指標訪問多了一個間接,從上面的代碼就可以看出來了)。

這兩個好處在系統級和嵌入式方面的編程裡面是非常重要的,所以對於這個技巧也用的比較廣。

但是,在C++中,這個是一個陷阱----一個讓你頭暈的陷阱。

因為C++的編譯器有可能在類class A的物件版面配置裡面插入一些東西,比如當要實現多態的時候,會向每個對象插入一個vptr(指向虛函數表的指標),插入的位置因編譯器而異(在g++中是插入在最前面,在vs2005中是插入在最後面),當它插入的是最後面的時候,那個技巧很可能就泡湯了。(而且,段錯誤會不定時的發生----當你調用虛函數的時候,段錯誤才會發生,還有其他一些我不知道的情況...)。而且我敢說,一旦出現這樣的問題,調試過程會相當的艱難,因為錯誤的地方距離問題出現的地方何止十萬裡~

因此,這種技巧在c++中充滿了危險,至少也是不可移植的~

還有類似的“陷阱”,比如

  1. struct A
  2. {
  3.     ...
  4. };
  5. struct A aA;

  6. memset( &aA, 0, sizeof(struct A) );

這個被在下評為C語言中將變數清0的最有效率之一的memset做法,到了C++中,如果你還這麼寫,那麼,我只能祝你好運~~----因為這種做法和上面的例子一樣,充滿了危險,尤其是當類裡面有虛函數的時候,那個時候,編譯器是要往對象裡面放東西的,現在你把這個東西清0了~,到某個時候再通過這個對象調用class A的虛函數試試你會哭不?(還有虛基類也是如此,略)
下面為了方便,

特例提供一下例子,以供娛樂(本例子僅供娛樂之用,如有別的效果,本人不負任何責任,呵呵):

  1. #include <iostream>
  2. using namespace std;

  3. class A
  4. {
  5. public:
  6.     virtual void f(){ cout << "aaaaaaaa" << endl;}
  7. private:
  8.     int a;
  9. };

  10. int main()
  11. {
  12.     A aA;
  13.     memset(&aA, 0, sizeof(A)); //把aA的指向虛函數表的指標也清0了
  14.     A *pa = &aA;
  15.     pa->aA; //用到了0的記憶體,出錯了
  16.     return 0;
  17. }

這篇筆記就說到這裡吧,老樣子,還是請各位可以多多指教,謝謝。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.