1. 程式人生 > >C++近期常見問題面試總結(一)

C++近期常見問題面試總結(一)

一、初始化列表:它的順序應該和宣告順序一致,否則會引起初始化錯誤

class A{
private:
	const int a;
	double b;
	char c;
public:
	A(int a_, double b_, char c_) : a(a_), b(b_), c(c_){}
};

在對類物件做賦值時,呼叫的拷貝建構函式,賦值呼叫的賦值過載
class B{
private:
	A obj_A;
	int b;
public:
	//使用初始化列表的形式
	B(A a, int b_) : A(obj_A), b(b_){}
	//使用正常構造方法的形式
	B(A a, int b_){
		this ->a = a;
		b = b_;
	}
};

(1).在初始化列表進行初始化操作時,首先const成員和引用必須在初始化列表中進行初始化
(2).而預設預設建構函式的類物件也必須在初始化列表中進行初始化,因為在建構函式中會先呼叫該類的預設建構函式
(3).對於有預設建構函式的類,初始化列表會呼叫賦值過載函式:operator=(),賦值過載函式會呼叫拷貝建構函式
而在建構函式中,會先呼叫預設建構函式,在呼叫賦值過載函式:operator=(),最後呼叫拷貝建構函式
因此初始化列表對於有預設建構函式的類物件會有更高的效率。

呼叫拷貝建構函式的三種情況,1.該物件作為引數時,2.該物件作為返回值時,3.初始化別的物件時。



二、空類
C++在底層實現時會保留一個位元組,因為不能讓物件不佔記憶體。
由於現在的系統都是按位元組編址,因為保留一個位元組作為空類的物件。但位元組裡沒有特定值。

編譯器會自動預設生成的函式:
1.default constructor
2.default distructor
3.copy constructor
4.operator=()
5.operator&()
6.operator&()const
這幾個函式雖然會預設生成,但是並不是說,肯定會生成它們
要是用不到,就不會生成

三、虛擬繼承的實現
假設有以下繼承體系
class Top{
		private :
			int a;
	};
	class Left : public Top{
		private :
			int b;
	};
	class Right public Top{
		private :
			int c;
	}
	class Bottom : public Left, public Right{
		private :
			int d;
	};
	//建立Bottom物件
	Bottom * ptr_Bottom = new Bottom();


那麼在這個Bottom物件中的記憶體佈局如下


Left::Top::a Left::bRight::Top::aRight::cBottom::d
我們如果執行: Left * ptr_Left = ptr_Bottom;
操作是正常的,因為Bottom物件中首先繼承left,因此left物件就在前面

而如果我們執行: Right * ptr_Right = ptr_Bottom;


四、this指標
C++物件模型中,成員函式是不在物件的記憶體中的,物件的記憶體中只存放虛擬函式表、成員變數

在呼叫成員函式時,怎麼知道呼叫的哪個物件的成員函式,這一點是由this指標保證的
在成員函式的第一個引數,會預設有一個形參名為this的指標引數
哪個物件呼叫該成員函式,它的值就是誰的地址值
所以可以通過this->data來訪問該物件的資料成員
而*this則表示該物件
所以說,對於this指標一個類只有一份
因為函式只有一份

const 用法:
1.const修飾普通變數,表示該變數為常變數,不能被修改
2.cosnt修飾指標,會優先修飾資料型別,否則才會修飾*
int const * a;表示a指向的是常量
const int * a;表示a指向的是常量
int * const a;表示a是一個常量指標,所指的物件不能被修改
3.const修飾引用,與修飾指標相同
4.const修飾函式:void fun()const;其實等價於:void fun(const className * this);
const修飾函式的功能是通過作用在this指標上完成的。因此const只能修飾成員函式,不能修飾static函式或普通函式
五、多型
多型分為編譯時多型(過載)和執行時多型(多型)
1.函式過載: 由於C++對函式處理比較特殊,如void fun(int a, char b)轉換成fun_int_char這種形式,所以不同的引數型別和各種就可以形成不同的函式
這也是過載的定義,函式名稱相同,函式的引數個數和引數型別不同,注意此處不要求返回值
多個過載的函式,實際形成的函式名會根據引數列表的不同而劃分,是不是在編譯的時候,呼叫不同的函式,呼叫時就會函式列表進行對比最終匹配到引數列表相同的函式
2.函式多型
對於含有虛擬函式的類,它的例項化物件中會有一個虛擬函式指標,該指標指向虛擬函式表。
函式會被放在符號表裡
通過查符號表知道呼叫哪個函式,這都是編譯過程完成的
虛擬函式,虛擬函式表類似於符號表,不過它存的是虛擬函式的地址
然後,呼叫哪個虛擬函式和符號表一樣,都是查表的過程
所以,虛擬函式的引入其實是會拖慢效率的
父類的相同函式被定義為虛擬函式,該類的派生類的相同函式自動被虛化,無論有沒有加virtual關鍵字,但是一般習慣是給子類加上virtual,為了閱讀方便
而虛擬函式表一般都被放置於物件的頭4個位元組