C++ 快速回顧(四)
- 前言
- 一、純虛函數
- 二、final關鍵字
- 1.作用到函數
- 2.作用到類
- 三、虛函數原理
- 四、Lambda一些知識補充
前言
用于快速回顧之前遺漏或者補充C++知識
一、純虛函數
純虛函數主要是當接口,沒有具體的實現要到派生類去實現。
- 純虛函數不能直接實例化,類似c#中的抽象函數
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};int main()
{//MyClassBase Base; 不能實例化system("pause");return 0;
}
- 純虛函數的派生類,必須實現了純虛函數才能實例化
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};class MyClass : public MyClassBase
{};int main()
{//MyClass Class; 不能實例化system("pause");return 0;
}
- 正確的使用方式
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};class MyClass : public MyClassBase
{
public:virtual void Init() override{}virtual void Destroy() override{}
};int main()
{MyClass Class; // 可以實例化system("pause");return 0;
}
二、final關鍵字
final 主要是處理不想繼續往下派生,禁止往下派生的情況
很像C#中的密封
1.作用到函數
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};class MyClass : public MyClassBase
{
public:virtual void Init() override{}virtual void Destroy() override final{}
};class ChildClass : public MyClass
{
public:virtual void Init() override{}// 無法重寫//virtual void Destroy() override//{////}
};
2.作用到類
無法繼續派生,不能用final類作為基類
class MyClassBase
{
public:virtual void Init() = 0;virtual void Destroy() = 0;
};class MyClass final : public MyClassBase
{
public:virtual void Init() override{}virtual void Destroy() override{}
};// 無法繼續派生,不能用final類作為基類
class ChildClass : public MyClass
{};
三、虛函數原理
要弄懂這個問題,我們要從最基本的類的內存大小來看
下面的這個空類,所占的大小是1字節,可以說這一字節是用來占位的
class MyClass
{};int main()
{int size = sizeof(MyClass);std::cout << size << std::endl;system("pause");return 0;
}
可以看到當有個int類型的變量后大小變為了4
class MyClass
{int Value = 0;
};int main()
{int size = sizeof(MyClass);std::cout << size << std::endl;system("pause");return 0;
}
那如果加個函數大小會有什么變化?答案是仍然為4
class MyClass
{int Value = 0;void Init() {}
};int main()
{int size = sizeof(MyClass);std::cout << size << std::endl;system("pause");return 0;
}
如果我們寫個虛函數可以發現大小變成了16
class MyClass
{virtual void Init(){}
};class MyClass1 : public MyClass
{int a = 0;
};int main()
{int size = sizeof(MyClass1);std::cout << size << std::endl;system("pause");return 0;
}
那這時候我們寫多個虛函數呢?答案也是16,可以看到只要有一個虛函數之后再有多少個虛函數大小都是16了。
當我們有虛函數時編輯器會為其生成虛函數表指針(vptr) 這個虛函數表指針會指向一個虛函數表,里面存儲著虛函數,當我們復寫時會覆蓋表中的函數導致重寫后調用了新的函數。
但是為什么大小是16呢?因為在64位操作系統中虛函數表指針(vptr) 占8個字節,4+8 = 12 也不是16 ? 這是因為內存對齊的緣故通常8字節對齊。所以就是16字節了。
class MyClass
{virtual void Init(){}virtual void Init1(){}virtual void Init2(){}virtual void Init3(){}
};class MyClass1 : public MyClass
{int a = 0;
};int main()
{int size = sizeof(MyClass1);std::cout << size << std::endl;system("pause");return 0;
}
四、Lambda一些知識補充
一般的Lambda就不細講了,只補充不知道的知識
注意這里不能直接傳入,是因為Lambda傳入的buffer 是加個Const的
int main()
{char buffer[1024] = "Hello World !!!";auto Test = [buffer](char* Value1){auto Test1 = [](char* Value2){printf(Value2);};Test1(buffer); // 注意這里不能直接傳入,是因為Lambda傳入的buffer 是加個Const的};system("pause");return 0;
}
加個const 即可
int main()
{char buffer[1024] = "Hello World !!!";auto Test = [buffer](char* Value1){auto Test1 = [](const char* Value2){printf(Value2);};Test1(buffer);};system("pause");return 0;
}