題目(六):運行下列C++代碼,輸出什嗎?
struct Point3D{ int x; int y; int z;}; int _tmain(int argc, _TCHAR* argv[]){ Point3D* pPoint = NULL; int offset = (int)(&(pPoint)->z); printf("%d", offset); return 0;}
輸出結果為8。pPoint地址為0,然後&((pPoint)->z)只是做了去地址操作,返回的是z在結構體中的地址
題目(七):運行下列C++代碼,輸出什嗎?
class A{public: A() { Print(); } virtual void Print() { printf("A is constructed.\n"); }}; class B: public A{public: B() { Print(); } virtual void Print() { printf("B is constructed.\n"); }}; int _tmain(int argc, _TCHAR* argv[]){ A* pA = new B(); delete pA; return 0;}
輸出
A is constructed.
B is constructed.
因為B繼承A,所以先初始化A,在初始化B,A雖然有虛函數但是還是輸出A的print,然後B輸出B的
題目(九):在C++中,struct和class有什麼不同?
struct其實作用和class類似,但是預設情況下,如果沒有標明函數或遍曆的許可權的情況下,struct中為public,而class中為private
題目(一):我們可以用static修飾一個類的成員函數,也可以用const修飾類的成員函數(寫在函數的最後表示不能修改成員變數,不是指寫在前面表示傳回值為常量)。請問:能不能同時用static和const修飾類的成員函數?
不明白題目什麼意思:
答案如下:
分析:答案是不可以。C++編譯器在實現const的成員函數的時候為了確保該函數不能修改類的執行個體的狀態,會在函數中添加一個隱式的參數const
this*。但當一個成員為static的時候,該函數是沒有this指標的。也就是說此時static的用法和static是衝突的。
我們也可以這樣理解:兩者的語意是矛盾的。static的作用是表示該函數只作用在類型的靜態變數上,與類的執行個體沒有關係;而const的作用是確保函數不能修改類的執行個體的狀態,與類型的靜態變數沒有關係。因此不能同時用它們。
題目(二):運行下面的代碼,輸出是什嗎?
class A{}; class B{public: B() {} ~B() {}}; class C{public: C() {} virtual ~C() {}}; int _tmain(int argc, _TCHAR* argv[]){ printf("%d, %d, %d\n", sizeof(A), sizeof(B), sizeof(C)); return 0;}
這道題目出的很好,自己也忘掉這種情況了,下面為網路上面的解釋,感覺很不錯
首先需要明白
程式運行過程中,所用到的儲存結構
代碼區:儲存程式的代碼
資料區:資料區存放全域變數和靜態變數,與常量 其實可以細化為全域/待用資料區與常量資料區
堆區:動態分配使用的。
棧區:存放局部變數與傳來的參數
類在記憶體裡的資料連續儲存,基本上就是存幾個非靜態成員變數與虛函數表指標(如果存在)
然後需要明白sizeof這個操作符的作用範圍
“The sizeof operator gives the amount of storage, in bytes, required to store an object of the type of the operand.”,而類中的函數代碼在“代碼區”,所以sizeof返回的A類型的對象佔用的記憶體空間不包括函數。
The sizeof operator cannot be used with the following operands:
Functions. (However, sizeof can be applied to pointers to functions.)
Bit fields.
Undefined classes.
The type void.
Dynamically allocated arrays.
External arrays.
Incomplete types.
Parenthesized names of incomplete types.
最後還有一個解釋很合理,很準確
類裡面占空間的是成員變數,如果有虛函數的話,編譯器會插入虛表指標,也占空間,如果由純虛基類的話,看編譯器的實現,可能會比+基類大,也可能會小。此外還要考慮記憶體對齊所浪費的空間。
ps:如果類為空白,或由純虛空基類派生出的空類的話,編譯器可能會做調整,使其大小不是0.
海濤部落格裡的答案
分析:答案是1, 1, 4。class A是一個空類型,它的執行個體不包含任何資訊,本來求sizeof應該是0。但當我們聲明該類型的執行個體的時候,它必須在記憶體中佔有一定的空間,否則無法使用這些執行個體。至於佔用多少記憶體,由編譯器決定。Visual
Studio 2008中每個空類型的執行個體佔用一個byte的空間。
class B在class A的基礎上添加了建構函式和解構函式。由於建構函式和解構函式的調用與類型的執行個體無關(調用它們只需要知道函數地址即可),在它的執行個體中不需要增加任何資訊。所以sizeof(B)和sizeof(A)一樣,在Visual
Studio 2008中都是1。
class C在class B的基礎上把解構函式標註為虛擬函數。C++的編譯器一旦發現一個類型中有虛擬函數,就會為該類型產生虛函數表,並在該類型的每一個執行個體中添加一個指向虛函數表的指標。在32位的機器上,一個指標佔4個位元組的空間,因此sizeof(C)是4。
總結來說:一個空類的空間大小雖然實際上為0,但是編譯器會最佳化,至於多少沒有一個準確的結構
sizeof計算的是所指對象佔用的空間,而類裡面的函數代碼完全在代碼區,不佔對象的空間
虛函數 在類中會隱含一個虛函數指標,佔用空間為4位元組,當然在空類中有虛函數就有空間,不必最佳化
題目(三):運行下面中的代碼,得到的結果是什嗎?
class A{private: int m_value; public: A(int value) { m_value = value; } void Print1() { printf("hello world"); } void Print2() { printf("%d", m_value); }}; int _tmain(int argc, _TCHAR* argv[]){ A* pA = NULL; pA->Print1(); pA->Print2(); return 0;}
這一題海濤接的十分好,因為 print1是函數,不佔用類對象的空間,此時類對象為空白,雖然使用print1函數,但是沒有訪問不能訪問的空間正確輸出
但是pa->print2()就出錯 因為使用了類對象,即this指標指向的m_value,沒有空間,當然訪存越界。
題目(五):靜態成員函數能不能同時也是虛函數?
不能:
靜態成員函數,不需通過this,即實際存在的對象來調用
虛函數,必須要通過實際存在的對象來調用,這兩個不能混
海濤答案:
分析:答案是不能。調用靜態成員函數不要執行個體。但調用虛函數需要從一個執行個體中指向虛函數表的指標以得到函數的地址,因此調用虛函數需要一個執行個體。兩者相互矛盾。
出處http://zhedahht.blog.163.com/。