1. 程式人生 > >C++重要知識點小結---1

C++重要知識點小結---1

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.

  1. int a = 1 , b = 0;  
  2. MAX(a++ , b);    //a被增值2次
  3. 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 出現在 * 兩邊,則兩者都為常量。

  1. <<effective C++>>上有個好記的方法:const在*號左邊修飾的是指標所指的內容;const在*號右邊修飾的是指標。  
  2. 簡單記就是:左內容,右指標。  

我只要一聽到被面試者說:"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的出現。

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.引數為結構或類:

  第一、結構或者類中的靜態成員不對結構或者類的大小產生影響,因為靜態變數的儲存位置與結構或者類的例項地址無關。

  第二、沒有成員變數的結構或類(非虛)的大小為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.一個類中將所有的成員函式都儘可能地設定為虛擬函式總是有益的。它除了會增加一些資源開銷,沒有其它壞處。

設定虛擬函式,需注意下列事項:

  1. 只有類的成員函式才能說明為虛擬函式。這是因為虛擬函式僅適用於有繼承關係的類物件,所以普通函式不能說明為虛擬函式。
  2. 靜態成員函式不能是虛擬函式,因為靜態成員函式不受限於某個物件。
  3. 行內函數不能是虛擬函式,因為行內函數是不能在執行中動態確定其位置的。即使虛擬函式在類的內部定義,編譯時,仍將其看作非內聯的。
  4. 建構函式不能是虛擬函式,因為構造時,物件還是一片未定型的空間。只有在構造完成後,物件才能成為一個類的名副其實的例項。
  5. 解構函式可以是虛擬函式,而且通常宣告為虛擬函式。