天天看點

C++面試題記錄(持續更新)

1、類模闆

函數模闆

template<typename T>
int compare(const T &v1, const T &v2)
{
	if(v1 < v2) return -1;
	if(v2 < v1) return 1;
	return 0;
}
           

類模闆 

template <typename T>
class Complex{
    
public:
    //構造函數
    Complex(T a, T b)
    {
        this->a = a;
        this->b = b;
    }
    
    //運算符重載
    Complex<T> operator+(Complex &c)
    {
        Complex<T> tmp(this->a+c.a, this->b+c.b);
        return tmp;
    }
        
private:
    T a;
    T b;
}
           

2、虛函數、構造與析構

虛函數是C++中實作多态的一種方法,其中隻聲明不實作的虛函數稱為純虛函數,包含純虛函數的類稱為純虛類,純虛類不可以被執行個體化。

子類構造時先執行父類的構造函數,然後再執行子類的構造函數;析構時相反,先執行子類的析構函數,再執行父類的析構函數。

基類的析構函數要聲明為虛函數,避免記憶體洩漏。

3、智能指針

share_ptr,unique_ptr, weak_ptr。

4、public,protect,private使用

public:類、子類和執行個體都可通路,繼承時是public繼承,子類可通路public成員,不可通路protect、private成員。

protect:類、子類可通路,執行個體不可通路。繼承時基類中的所有成員在派生類中變成了protect。

private:類本身才可通路。繼承時基類中的所有成員變成了private。

5、封裝接口注意事項

6、對于一個空類,編譯器預設做了哪些操作

預設添加了:構造函數、析構函數、拷貝構造函數、指派運算符、取址運算符、this指針。

需說明的是,對于一個沒有執行個體化的類,編譯器是不會添加上述函數的,隻有執行個體化時,才會預設生成相應的函數,同時,開辟一段記憶體空間。

update20190217:隻有當上述函數被編譯器需要時,才會被編譯器預設添加。

具體場景參見:https://www.cnblogs.com/QG-whz/p/4676481.html

7、靜态變量初始化時機、存儲區域、是否線程安全

靜态變量在編譯過程中進去main()函數之前就已經被初始化了,C++在進入程式進入點前,編譯器會執行StartUp代碼,其作用為函數庫的初始化、進行資訊設立、I/OStream産生及static對象的初始化操作(調用構造函數)。靜态變量存儲在全局區,生命周期為整個程式的生命周期。靜态對象在構造時是線程安全的,當有一個線程執行static類對象的構造函數時,其他欲通路該static類對象的線程都是阻塞的。但是在靜态對象構造完畢後,其内部的靜态成員是非線程安全的。

8、多重繼承(菱形繼承)

C++面試題記錄(持續更新)

解決菱形繼承的問題是使Base1和Base2這兩個類繼承Base的時候變為虛繼承,即Base1:: virtual public Base, Base2::virtual public Base,這樣執行個體出來的Derive對象中将隻有一個base對象。

當然,也可以指定特定基類的方式通路基類變量,如下:

Derive d;

d.base =3; // 不正确

d.Base1::base = 3; // 正确

9、new和malloc的差別

malloc是标準庫函數,new 是C++的運算符,都可用于申請動态記憶體。

由于malloc是庫函數而不是運算符,不在編譯器控制權限之内,不能把執行構造函數的任務加于malloc。

new運算符可以執行記憶體開辟、執行構造函數、記憶體的配置設定。

10、const 指針

了解const指針和指向const的指針技巧在于檢視const關鍵字右邊來确定什麼被聲明為常量。

const char *p 指向const char的指針,p可以改變指向,但是p指向的值不能改變;

char* const p 定義常量指針p,不可以改變其指向,但是可以通過指針來改變其指向的值。

以下程式的輸出結果:

char str1[]       = "abc";  

char str2[]       = "abc";  

const char str3[] = "abc";   

const char str4[] = "abc";   

const char* str5  = "abc";  

const char* str6  = "abc";  

cout << boolalpha << ( str1==str2 ) << endl; // 輸出什麼?  

cout << boolalpha << ( str3==str4 ) << endl; // 輸出什麼?  

cout << boolalpha << ( str5==str6 ) << endl; // 輸出什麼?  

複制代碼

【參考答案】

分别輸出 false,false,true。

str1和str2都是字元數組,每個都有其自己的存儲區,它們的值則是各存儲區首位址,不等;

str3和str4同上,隻是按const語義,它們所指向的資料區不能修改。

str5和str6并非數組而是字元指針,并不配置設定存儲區,其後的“abc”以常量形式存于靜态資料區,而它們自己僅是指向該區首位址的指針,相等。

11、模闆函數是否聲明和定義是否可以分開?

模闆函數的聲明和定義不能分開。編譯的過程中,編譯器遇到使用函數的地方時,訓示連結器在其他的.obj檔案中需找目标函數的實作體。模闆函數隻有在使用的地方才進行執行個體化,是以當編譯器隻看到模闆的聲明時,并不能執行個體化該模闆,隻能建立一個具有外部連結的符号并期待連結器能夠将符号的位址決議出來。當

繼續閱讀