C++複試常見題集結

1.delete,malloc,new,free四者之間的關係
我們在進行C++程序編寫的時候,不可避免的會使用面向對象的方式,但是對於我們自己編寫的類來說,我們通常稱之爲非內部的數據結構類型,此時對於free/malloc這種標準的C/C++庫函數來說,是不可能完成執行構造函數和析構函數的作用的,而C++的標準運算符new和delete可以完成此項工作,new用於進行動態的內存分配和初始化工作,delete可以完成對象的清理和釋放工作。
2.delete和delete[ ]的區別
我們在進行面向對象的程序設計時,會自建數據類型,但是對於我們通過new出來的自建數據類型的釋放有需要注意的地方。簡而言之就是用new分配的,需要通過delete來進行相應的釋放,而通過new[ ]分配的內存,需要通過delete [ ]來進行釋放,但是對於內部已有的數據類型來說不存在此種限制。
3.C++面向對象三大特性:封裝 繼承 多態
4.子類的析構和基類的析構的調用情況
一句話,基類和子類之間的構造或者析構函數可以通過洋蔥圈模型類予以解釋,調用構造函數時,會先調用基類的構造函數,然後深入子類,而析構正好與之相反,先調用子類的,再調用父類的。
5.多態 虛函數 純虛函數
首先多態產生的條件便是繼承,方法重寫,父類引用指向子類對象。會通過父類來根據相同的指令調用子類不同的方法,而虛函數和純虛函數之間是有區別的,虛函數需要定義加上代碼的實現,而純虛函數不需要,並且如果一個類中如果存在純虛函數,那麼此類不能進行實例化,只能繼承,虛函數便沒有此種限制。
6.引用 以及需要注意的問題
引用便是我們在操作某一個變量時所起的別名,引用在創建時本身就不是一個數據類型,並不佔有存儲單元,因此係統也不會爲之分配內存,引用聲明以後,就相當於存在兩個名字指向一塊地址,但是不能再爲引用創建引用。
7.將引用作爲函數參數的特點是什麼
將目標變量的引用作爲函數的參數和將指針作爲函數的參數的效果相同,但是不同的是我們需要對指針作爲的形參分配存儲空間,而對引用作爲的形參不需要分類存儲空間。
8.什麼時候使用常引用
如果我們需要提高程序的效率,又希望我們的程序變量在函數內部不進行改變,那我們可以通過常引用的方式來進行編寫程序。
9.全局變量和局部變量相關
C++的內存區域可以分爲堆區和棧區,以及靜態存儲區,局部變量存儲在棧區,函數結束後自動進行釋放,全局變量存儲在靜態存儲區,程序退出後才進行釋放,另外堆區存放的是由new,malloc開闢,需要通過程序員本身調用delete,free進行釋放。
10.基類的析構函數不是虛函數,會帶來什麼問題
在面向對象程序設計中,我們經常會見到虛函數,但是並不是每一個類的析構函數都是虛函數,如果某一個類爲基類並且產生繼承和多態時,一般將析構函數設置爲虛函數,如果不這樣做的話,那麼在父類指針指向子類對象的時候,父類指針此時的析構函數並不是虛函數,在delete此指針的時候,只會調用父類的,而不會調用子類的,會導致內存泄漏。
11.介紹內存的分配方式
程序運行起來會產生3個區,主要的變量都會幾種在這三區內。
首先是靜態存儲區,程序運行開始便出現,其內的主要成員保羅全局變量等等,在程序運行結束後進行釋放。
其次是棧區,主要存儲函數的局部變量,在函數內部有效,函數執行結束後會被自動釋放掉。
最後是棧區,主要通過new或者malloc方式來開闢內存,有程序員手動釋放。
12.const VS #define
const常量與宏常量define之間使用方式類似,但是const應用時會進行安全類型檢查,在程序的編譯,運行時起作用,而define則在程序的預處理階段,只進行簡單的字符串轉換。並且某些編譯器可以對const進行調試,而不能對宏常量進行調試,使用const可以避免不必要的內存分配,節省空間。
13.代碼識別

void * ( * (*fp1)(int))[10];   //1

解釋:首先fp1是一個指針,指向一個函數,這個函數的參數爲int類型,函數的返回值也是一個指針,這個指針是一個數組,這個數組有10個元素,每一個元素是一個void*指針。

float (*(* fp2)(int,int,int))(int); //2

解釋:fp2是一個指針,指向一個函數,這個函數有三個int類型的參數,函數返回值也爲指針,指向一個函數,這個函數的參數爲int類型,返回值爲float類型。

int (* ( * fp3)())[10]();    //3

解釋:fp3是一個指針,指向一個函數,這個函數的參數爲空,函數的返回值也爲一個指針,這個指針指向一個數組,這個數組有10個元素,每一個元素是一個指針,指向一個函數,函數的參數爲空,返回值爲int類型。

int id[sizeof(unsigned long)];  //4

解釋:上面的代碼正確,sizeof爲編譯時的元素符,編譯時便確定了,可以看成與機器有關的常量。

 int (*s[10])(int);  //5

解釋:爲一個函數指針數組,首先第一個int爲返回值,而*s[10]爲指針數組,s是含有10個指針的數組,第二個int是參數列表,(*p)(int)是一個函數指針,所以總計爲一個函數指針數組。

    char str1[] = "abc";
  char str2[] = "abc";

  const char str3[] = "abc";
  const char str4[] = "abc";

  const char *str5 = "abc";
  const char *str6 = "abc";

  char *str7 = "abc";
  char *str8 = "abc";

  cout << ( str1 == str2 ) << endl;//0  分別指向各自的棧內存
  cout << ( str3 == str4 ) << endl;//0  分別指向各自的棧內存
  cout << ( str5 == str6 ) << endl;//1指向文字常量區地址相同

  cout << ( str7 == str8 ) << endl;//1指向文字常量區地址相同

解釋:str1到str4都是數組常量,他們都有自己的內存地址或者內存空間,但是str5到str8爲指針,他們都指向相同的區域。

int  a=4;

int  &f(int  x)

{    a=a+x;

      return  a;

}

int main(void)

{    int   t=5;

     cout<<f(t)<<endl;    //a = 9

    f(t)=20;              //a = 20

    cout<<f(t)<<endl;     //t = 5,a = 20  a = 25

     t=f(t);               // a = 30 t = 30

    cout<<f(t)<<endl;  }   // t = 60

}

14.引用和指針的區別
引用必須進行初始化,但是指針不需要,而且引用一旦初始化,便不可以更改其指向,更不可一指向空,但是指針不僅可以爲一個空指針,而且可以更改指針的指向。
15.結構和聯合
結構和聯合都是由多個不同的數據類型成員組成,但在同一時刻,聯合中值存放了一個被選中的成員,而結構的所有成員都存在。
對於聯合的不同成員賦值,將會對其他成員進行重寫,原來成員的值就不存在了,對於結構的不同成員賦值是不影響的。
16.重載和重寫
重載是指重新編寫同名函數,但是必須滿足函數的參數不同,參數個數或者類型不同的前提條件,並且,重載和多態無關,但是重寫不同,多態發生時便發生了重寫。
另外關於地址綁定,重載是早綁定,在編譯期間便綁定完畢,是靜態的,但是重寫是運行時綁定,屬於晚綁定。
17.全局對象的構造函數會在main函數之前執行,並且C++不是類型安全的,兩個不同類型的指針可以進行轉換,在這方面C#是安全的.關於initialization list,如果一個類所有成員都是public且沒有默認的構造函數,就可以用initialization list對類的成員進行初始化;assignment爲賦值
18.UDP和TCP
UDP爲用戶報文協議,TCP爲傳輸控制協議,TCP與UDP相比較而言更加安全可靠,但是UDP更加快讀,使用UDP還是TCP要取決於程序要求。
19.消息映射
程序員指定MFC類(有消息處理能力的類)處理某個消息,完成對處理函數的編寫, 來完成消息處理的功能。
20.windows消息系統由哪幾部組成
windows的消息系統由三部分組成,分別是消息隊列, 消息循環以及消息處理。
操作系統負責爲進程準備一個消息隊列,程序不斷從消息隊列中收取消息,接收消息。而應用程序也可以通過消息循環不斷獲取消息,處理消息。
消息處理便是消息循環將消息放到關聯的窗口上進行處理。
21.將類的聲明和實現分開的好處
可以起到保護的作用,其實可以提高編譯的效率。
22.局部變量和全局變量
局部變量和全局變量的名字可以相同,但是局部變量會屏蔽全局變量,如果需要在同名的情況下使用全局變量,需要使用域運算符(::)。
23.assert()函數的使用
assert函數是一個調用程序時經常使用的宏,在程序運行時用來計算括號內的表達式,其宏定義存放在<assert.h>中,其函數原型爲void assert(int expression);類似於python中的assert,如果我們在打開文件時進行assert,會起到很好的作用。在程序運行時會計算括號內的表達式,如果出錯,則會終止程序的進行。
24.關於枚舉類型
首先何爲枚舉類型,所謂的枚舉類型便是C++的一種派生類型,是用戶定義的若干枚舉常量的集合,其聲明形式爲enum 枚舉名 {變量列表}。例如如果我們有一個需求那就是系統記錄一週的變量的那便是enum Weekday{SUN,MON.TUE,WED,THU,FRI,SAT};
值得注意的是:當我們需要一個變量,這個變量有好幾種可能的取值的時候,我們可以將他定義爲枚舉類型。枚舉類型有利於提高程序的可讀性,從某種意義上來將,我們可以將其稱之爲一種“語法糖”。
25.class和struct
如果沒有繼承或者多態,那麼class和struct兩者的存儲效率差不多相同,但是在C++中,class和struct是有着區別的,class成員默認爲私有的,而struct默認爲公有的。class和可以定義模板參數,但是struct不支持。
26.static函數和普通函數的區別
static靜態函數默認的代碼只限於本文件所有,而普通函數可以被其他代碼文件所調用。
總結來說就是,其他文件可以擁有同名靜態函數,靜態函數不可被其他文件所有。
27.指針的幾種情況
int p[n]:指針數組,一共n個元素,每個元素均爲指向整型數據的指針.
int (
)p[n]:p爲一個指針,指向一維數組,這個數組有n個整形數據。
int p():函數指針,p指向函數的返回值
int (
)p():p爲指向函數的指針。
28.Debug和Release版本的區別
Debug是調試版本,Release是最終發送給用戶的非調試的版本。
29.函數指針和指針函數
函數指針指的是指向一個函數入口的指針,而指針函數指的是函數的返回值是一個指針類型。
30.指針常量和常量指針
指針常量(int * const p),本質上是一個常量,指針用來說明常量的類型,在指針常量中,指針指向的值可以更改,但是指向的地址不可以更改。
常量指針(const int * p),本質上是一個指針,指針指向一個常量,指針指向的內容不可以更改,但是指向可以更改。
31.對指針的理解
指針是一個變量,指向一塊內存地址,指針的類型取決於指針指向的類型,其也可以訪問其指向的內存地址。
32.面向對象相關話語
面向對象的程序設計思想便是將數據結構和對數據結構的操作的方法封裝成一個個的對象,而類便是將一些具有共性的對象封裝起來,對象所具有的特徵包括靜態特徵和動態特徵。靜態特徵指的是描述對象的一些屬性,動態特徵指的是對象表現出來的行爲。
類的定義與實現寫在不同的文件上會提高編譯的效率,因爲分開的話只需要編譯一次對應的obj文件,再次應用該類的地方就不會被編譯,大大提高了效率。
–》成員函數通過this指針指向對象的首地址來區分不同對象的成員數據。
–》C++自動爲類生成了四個缺省函數爲:默認構造函數 拷貝構造函數 析構函數 賦值函數
33.關於內置函數
C++中類的成員函數定義可以分爲幾種實現方式,但是如果我們在類的內部實現了成員函數,我們默認實現的爲較小規模的,但是系統在調用函數過程所花費的時間開銷是巨大的。因此如果系統爲了減少時間的開銷,如果類內實現的成員函數不包括循環等控制結構,系統會默認將其編譯爲內置函數。默認inline定義,如果類內實現,那麼便可以省略inline.
34.拷貝構造函數調用時機
①當一個對象去初始化另一個類的對象的時候
②如果函數的形參是類的對象,調用函數進行實參和形參結合的時候。
③如果函數的返回值是類對象,函數調用完成返回時。
關於構造函數,構造函數是類的一種特殊的成員函數,一般情況下,用來初始化對象成員變量,構造函數名字必須與類名相同,不具有任何類型,不具有返回值。
35.重寫拷貝構造函數
通常情況下的一個原則是,如果我們在一個類中進行了new操作,我們便需要一個析構函數,同時我們也便需要一個拷貝構造函數。重寫拷貝構造函數的原則便是包含動態分配成員或者包含指針成員的類都應該提供拷貝構造函數,同時提供拷貝構造函數的同時還應該考慮到重載“=”運算符。
另外,構造函數的調用順序爲先調用基類的構造函數,然後順序初始化成員,然後調用自己的拷貝構造函數。
36.初始化成員列表的使用
首先,類對象的構造順序爲,分配內存,調用構造函數,顯示或者隱式的初始化數據成員。
在以下三種情況下我們需要使用初始化列表:
①如果我們有一個類成員,本身就是一個類或者是一個結構,而且這個成員只有一個帶參數的構造函數,而沒有默認構造函數,如果要對此類進行初始化,就必須調用這個類成員的帶參數的構造函數,如果沒有初始化列表,第一步將無法完成。
②當類成員中含有一個const對象的時候,或者是一個引用的時候,也必須通過初始化成員列表進行初始化,因爲這兩種對象在聲明後需要馬上進行初始化操作,而在構造函數中賦值會報錯。
③子類初始化父類的成員,僅僅只能在初始化列表中進行初始化。
37.靜態成員函數
當我們在一個類中定義了靜態私有成員的時候,只能通過靜態成員函數來進行訪問。當類的構造函數是私有的時候,不能像普通的類那樣實例化自己,只能通過靜態成員函數來調用構造函數來初始化自己。另外,如果我們想要在類外訪問類的私有成員,我們可以通過下面的三種方式來進行訪問,分別是,友元,繼承以及共有的成員函數。
抽象類指的便是隻能用來繼承,而不能進行私有化的類。
運算符重載的意義在於爲了使得用戶自定義的數據類型的操作和內定義的數據類型的操作想同,運算符重載的三種方式分爲普通函數,友元函數以及類成員函數。* 、sizeof、.、s三目元算符以及域運算符都不可以進行重載。
賦值運算符和拷貝構造函數之間的區別爲都是將一個對象拷貝到另一箇中去,不同的是拷貝構造函數需要建立一個新對象。
構造函數可以被重載,析構函數有且只有一個,且沒有參數,不可以被重載。
全局對象的構造函數會在main之前執行。
38.類A
對一個類A不聲明任何的成員函數和成員變量,但是Sizeof(A)仍不爲0,舉個反例,如果我們定一個class A[10]對象數組,如果爲0,那麼就無法區分A[0] A[1]…
堆棧溢出的原因一般是沒有回收垃圾資源。構造函數不能聲明爲虛函數。
IP地址由兩部分組成,分別爲網絡號和主機號。
switch()內的不能爲浮點型,必須爲整型或者枚舉型。
一個函數頻繁調用,C中爲宏定義,C++爲內聯函數。
C++不是安全的,因此兩個不同類型的指針可以進行強制轉換。
C++值的傳遞方式:值傳遞 指針傳遞 引用傳遞
引用的時候加上尖括號表示從標準庫路徑開始查找,不加則從用戶的工作目錄開始查找。
39.static操作符
①static+局部變量 將一個變量聲明爲函數的局部變量,函數結束後變量不會被釋放掉。
②static+全局變量 表示一個變量在當前文件的全局內科訪問
③static+函數 表示一個函數在當前文件的全局內可訪問
④static+類成員變量 表示這個成員爲類所共有
⑤static+類成員函數 表示這個函數爲全類所共有,而且只能訪問靜態成員變量
其作用是static+局部變量表示變量的作用範圍爲該函數體,該變量的內存只被分配一次,在下次調用時還維護上次的值。
static+全局變量或者函數指的是對整個模塊可訪問,其他模塊不可訪問。
static+類相關,表示在類共有,且static+類函數只能訪問靜態成員,不接受this指針。
40.const操作符
const修飾常量,定義時就被初始化,以後不能更改。const修改形參,那麼該形參在函數體內不能進行任何的改變。
const修飾類成員函數,表示該函數只能對成員變量進行只讀操作。
const用來阻止一個變量被改變。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章