1.C++中類與結構的唯一區別是:類(class)定義中默認情況下的成員是private的,而結構(struct)定義中默認情況下的成員是public的。
2. ::叫作用域區分符,指明一個函數屬於哪個類或一個數據屬於哪個類。::可以不跟類名,表示全局數據或全局函數(即非成員函數)。
3.類名加載成員函數名之前而不是加在函數的返回類型前。
錯誤:Tdate::void Set(int m , int d , int y) {}
正確: void Tdate::Set(int m , int d , int y) {}
4.一個類對象所占據的內存空間由它的數據成員所占據的空間總和所決定。類的成員函數不占據對象的內存空間。
5.類的成員函數可以訪問該類的private成員。
6.類作用域是指類定義和相應的成員函數定義范圍。在該范圍內,一個類的成員函數對同一類的數據成員具有無限制的訪問權。
7.#include <filename.h> 和#include “filename.h” 有什么區別?
答:
- 對於#include <filename.h> ,編譯器從標准庫路徑開始搜索filename.h
- 對於#include “filename.h”,編譯器從用戶的工作路徑開始搜索filename.h
8.
- int a = 1 , b = 0;
- MAX(a++ , b); //a被增值2次
- MAX(a++ , b + 10); //a被增值1次
MAX(a++ , b)的值為2,同時a的值為3;
MAX(a++ , b + 10)的值為10,同時a的值為2
9.類定義是不分配空間和初始化的。類是一個抽象的概念,並不是一個實體,並不含有屬性值,而只有對象才占有一定的空間,含有明確的屬性值。
10.運行如下代碼:
class A { public: A(int j):age(j) , num(age + 1) //... protected: int num; int age; }; void mian() { A sa(15); }
代碼運行結果:num=“隨機值 ”, age= 15
由於按成員在類定義中的聲明順序進行構造,而不是按構造函數說明中冒號后面的順序,所以num成員被賦的是一個隨機值,並不是想賦的16,因為這個時候,成員age還沒有被賦值,age的內存空間中是一個隨機值。
11.如果 const 出現在 * 左邊,則指針指向的內容為常量;如果 const 出現在 * 右邊,則指針自身為常量;如果 const 出現在 * 兩邊,則兩者都為常量。
- <<effective C++>>上有個好記的方法:const在*號左邊修飾的是指針所指的內容;const在*號右邊修飾的是指針。
- 簡單記就是:左內容,右指針。
我只要一聽到被面試者說:"const意味着常數",我就知道我正在和一個業余者打交道。去年Dan Saks已經在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應該非常熟悉const能做什么和不能做什么.如果你從沒有讀到那篇文章,只要能說出const意味着"只讀"就可以了。盡管這個答案不是完全的答案,但我接受它作為一個正確的答案。(如果你想知道更詳細的答案,仔細讀一下Saks的文章吧。)如果應試者能正確回答這個問題,我將問他一個附加的問題:下面的聲明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個的作用是一樣,a是一個常整型數。第三個意味着a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針可以)。第四個意思a是一個指向整型數的常指針(也就是說,指針指向的整型數是可以修改的,但指針是不可修改的)。最后一個意味着a是一個指向常整型數的常指針(也就是說,指針指向的整型數是不可修改的,同時指針也是不可修改的)。如果應試者能正確回答這些問題,那么他就給我留下了一個好印象。順帶提一句,也許你可能會問,即使不用關鍵字const,也還是能很容易寫出功能正確的程序,那么我為什么還要如此看重關鍵字const呢?我也如下的幾下理由:
1). 關鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數為常量是為了告訴了用戶這個參數的應用目的。如果你曾花很多時間清理其它人留下的垃圾,你就會很快學會感謝這點多余的信息。(當然,懂得用const的程序員很少會留下的垃圾讓別人來清理的。)
2). 通過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。
3). 合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現。
const的用法參考:http://blog.csdn.net/hyg0811/article/details/9349869
12.C++一維數組和指針的關系總結
對於數組int a[10]; a表示數組的第一個元素的地址,即&a[0];
如果使指針p,指向數組的首元素,可以進行操作:int * p=a; 或者int *p=&a[0];
那么p++,是指向數組中的先一個元素,即a[1];
此時*p則是a[1]中所放的值。
此時,a[i]=p[i]=*(a+i)=*(p+i)
關於*p++,由於++和*的優先級相同,結合方向是自右而左,因此它等價於*(p++)。作用是:先得到p指向的變量的值(即*p),然后再使指向p的值加1.
*p++等價於*(p++);而*(++p)表示先使p+1,再取*p。
13.在VC中,sizeof有着許多的用法,而且很容易引起一些錯誤。下面根據sizeof后面的參數對sizeof的用法做個總結。
A.參數為數據類型或者為一般變量:
例如sizeof(int),sizeof(long)等等。
這種情況要注意的是不同系統系統或者不同編譯器得到的結果可能是不同的。
例如int類型在16位系統中占2個字節,在32位系統中占4個字節。
B.參數為數組或指針:
int a[50]; //sizeof(a)=4*50=200;求數組所占的空間大小
int *a=new int[50];// sizeof(a)=4; a為一個指針,sizeof(a)是求指針的大小,在32位系統中,當然是占4個字節。
C.參數為結構或類:
Sizeof應用在類和結構的處理情況是相同的,需要考慮字節對齊(參加另一篇文章:http://www.cnblogs.com/heyonggang/archive/2012/12/11/2812304.html)。另外有幾點需要注意:
第一、結構或者類中的靜態成員不對結構或者類的大小產生影響,因為靜態變量的存儲位置與結構或者類的實例地址無關。
第二、沒有成員變量的結構或類(非虛)的大小為1,因為必須保證結構或類的每一個實例在內存中都有唯一的地址。
第三、包含虛函數的類或者虛繼承的類,需要算上虛表指針的占的4個字節。
下面舉例說明:
Class Test{int a;static double c};//sizeof(Test)=4.
Test *s;//sizeof(s)=4,s為一個指針。
Class test1{ };//sizeof(test1)=1;
Class test2{ virtual void print(){}};//sizeof(test2)=4;
14.運算符new分配堆內存,如果成功,則返回指向該內存的空間,如果失敗,則返回NULL。所以每次使用運算符new動態分配內存時,都應測試new的返回指針值,以防分配失敗。
1 Person::Person(Person &p) 2 { 3 cout<<"Copying "<<p.pName<<"into this own book\n"; 4 pName = new char[strlen(p.pName) + 1]; 5 if(pName != 0) 6 strcpy(pName , p.pName); 7 }
15.如果你的類需要析構函數來析構資源,則它也需要一個拷貝構造函數。
由於C++提供的默認拷貝構造函數只是對對象進行淺拷貝復制。如果對象的數據成員包括指向堆空間的指針,就不能使用這種拷貝方式,此時必須自定義拷貝構造函數,為創建的對象分配堆空間。
16.類成員函數的重載、覆蓋和隱藏區別?
答案:
a.成員函數被重載的特征:
(1)相同的范圍(在同一個類中);(2)函數名字相同;(3)參數不同;(4)virtual 關鍵字可有可無。
b.覆蓋是指派生類函數覆蓋基類函數,特征是:
(1)不同的范圍(分別位於派生類與基類);(2)函數名字相同;(3)參數相同;(4)基類函數必須有virtual 關鍵字。
c.“隱藏”是指派生類的函數屏蔽了與其同名的基類函數,規則如下:
(1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
(2)如果派生類的函數與基類的函數同名,並且參數也相同,但是基類函數沒有virtual 關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)
17.《C++程序設計教程》P352
在例子中並沒有聲明派生類GraduateStudent的構造函數,根據類的實現機制,派生類對象創建時,將執行其默認的構造函數。該默認構造函數會先調用基類的默認構造函數,而基類沒有默認構造函數,但正好匹配默認參數的構造函數。
18.在運行時,能根據其類型確認調用哪個函數的能力,稱為多態性,或稱遲后聯編,或滯后聯編。編譯時就能確定哪個重載函數被調用的,稱為先期聯編。
多態性可可以簡單的概括為“一個借口,多種方法”,在程序運行的過程中才決定調用的函數。
虛函數就是允許被其子類重新定義的成員函數。而子類重新定義父類虛函數的做法,稱為“覆蓋”或“重寫”。
覆蓋是指子類重新定義父類的虛函數的做法。
重載是指允許存在多個同名函數,而這些函數的參數表不同。
為了指明某個成員函數具有多態性,用關鍵字virtual來標志其為虛函數。
如果虛函數在基類與子類中出現的僅僅是名字的相同,而參數類型不同,或返回類型不同,即使寫上了virtual關鍵字,則也不進行遲后聯編。
19.一個類中將所有的成員函數都盡可能地設置為虛函數總是有益的。它除了會增加一些資源開銷,沒有其它壞處。
設置虛函數,需注意下列事項:
- 只有類的成員函數才能說明為虛函數。這是因為虛函數僅適用於有繼承關系的類對象,所以普通函數不能說明為虛函數。
- 靜態成員函數不能是虛函數,因為靜態成員函數不受限於某個對象。
- 內聯函數不能是虛函數,因為內聯函數是不能在運行中動態確定其位置的。即使虛函數在類的內部定義,編譯時,仍將其看作非內聯的。
- 構造函數不能是虛函數,因為構造時,對象還是一片未定型的空間。只有在構造完成后,對象才能成為一個類的名副其實的實例。
- 析構函數可以是虛函數,而且通常聲明為虛函數。
