近兩週學習總結

<1>用了幾天把高效c++看了一遍(下面主要整理了自己平時容易遺忘或者沒有常用的知識點)
1. c++中的4中強制轉換
(1)const_cast
只能對指針或者引用去除或者添加const屬性,對於變量直接類型不能使用const_cast;不能用於不同類型之間的轉換,只能改變同種類型的const屬性。
(2)static_cast
類似於C風格的強制轉換。無條件轉換,靜態類型轉換。由較大類型轉換爲較小類型,如果是隱式的,編譯器通常會產生警告,如果我們顯示地提供強制類型轉換,則可以關閉警告信息。
(3)dynamic_cast
有條件轉換,動態類型轉換,運行時類型安全檢查(轉換失敗返回NULL): 1. 安全的基類和子類之間轉換。 2. 必須要有虛函數。 3. 相同基類不同子類之間的交叉轉換。但結果是NULL。
dynamic_cast涉及運行時類型檢查
(4)reinterpreter_cast
這種應該就是內存裏的數據不變(同一個二進制數),根據轉換的類型重新解釋,可以把指針轉換爲整形數,一般比較少見。
2. 析構函數中絕對不要吐出異常
原因:因爲析構函數通常乾的事情都是清理釋放對象持有的資源。如果在析構的過程中發生了異常就可能會導致資源泄露,導致程序出現不明確的行爲。
解決方式:
(1)在析構函數中加上異常捕獲的代碼,析構函數中可能出現異常的部分。當出現異常的時候,使用abort來強迫終止程序,這樣可以阻止異常從析構函數中傳遞出去,如果傳遞出去可能會導致不明確的行爲。也就是說使用abort可以搶先不明確的行爲與死地。
(2)在析構函數中捕獲異常,但是不強迫終止程序,默默地吞下異常。這種方案可以保證程序能夠繼續執行,有時候比草率的結束程序要好一些
(3)另外一種方式可以設計一個接口給用戶,另外加一個調用標誌isused。這個提供給用戶的結構實際上可以完成析構清理資源,關閉數據庫連接等的操作。用戶在他們的代碼中可以使用try-catch異常不活的語句來處理這個可能處理異常的部分,如果調用了接口,在接口代碼中設置isused=true。並且在析構函數中檢查接口是否被調用的標誌,如果接口沒有被用戶顯示的調用,在析構函數中就執行那部分可能會出異常的部分,同樣,在析構函數中處理的時候也是要加上try-catch來處理異常,防止因爲發生異常,傳遞出去導致程序不明確的行爲。
3. 以獨立語句將newd對象存儲於智能指針內,否則,一旦異常拋出可能導致難以察覺的資源泄漏。
例如:

func(tr1::shared_ptr<Base> ptr(new Base),fun1());

(1)在調用func必須做三件事:調用fun1();執行new Base;調用tr1::shared_ptr構造函數。
(2)c++以什麼次序完成上面三件事,彈性很大,只能確定new Base在調用tr1::shared_ptr構造函數之前。
(3)如果按照下列次序:new Base;fun1();調用tr1::shared_ptr構造函數。萬一fun1調用導致異常,可能導致資源泄漏。
改爲:

tr1::shared_ptr<Base>ptr(new Base);
func(ptr,fun1())。

4.避免遮掩繼承而來的名稱
名稱的遮掩可以分成變量的遮掩與函數的遮掩兩類,本質都是名字的查找方式導致的,當編譯器要去查找一個名字時,它一旦找到一個相符的名字,就不會再往下去找了,因此遮掩本質上是優先查找哪個名字的問題。
而查找是分作用域的,雖然本條款的命名是打着“繼承”的旗子來說的,但我覺得其實與繼承並不是很有關係,關鍵是作用域。
1. inline函數
(1)類似於C中的#define
在C++中,提供了inline函數來代替C中的宏定義。(通常可以使用const來代替單純變量的宏定義,它可以提供類型檢查。對於形似函數的宏,最好改用inline函數來替換宏定義。)
編譯器最優化機制通常被設計用來濃縮那些“不含函數調用“的代碼,所以當你inline某個函數時,或許編譯器就因此有能力對它執行語境相關最優化。
(2)效率問題
inline函數同#define宏定義一樣,都是以函數本體做替換,這樣做可能增加你的目標碼(object code),從而可能造成代碼膨脹(代碼膨脹會導致額外的換頁行爲,降低指令高速緩存裝置的擊中率,帶來效率損失)。如果inline函數本體很小,編譯器針對“函數本體”所產生的碼可能比針對“函數調用”所產生的碼可能更小。
(3)是申請,而不是強制,也不一定要帶inline。注意,inline只是對編譯器的一個申請,不是強制命令。
(4)構造函數和析構函數一般不應該是inline的
(5)對所有的virtual虛函數都不能申請爲inline函數
6.絕不重新定義一個繼承而來的缺省參數值,因爲缺省參數值是靜態綁定。而唯一應該覆寫的虛函數,卻是動態綁定。
7.明智審慎地使用private繼承
(1)私有繼承意味着根據某物實現出,通常比複合級別低。但當派生類需要訪問protected base的成員或要重新定義繼承而來的虛函數時,這麼設計是合理的。
(2)和複合不同,私有繼承可以empty base最優化。這對於空間要求高的開發而言很重要。
8.以前在學校感覺泛型編程這塊沒掌握牢固,最近又好好鞏固了這塊的知識
<2>學習了下qt裏面的一些知識
9.模態、非模態、半模態對話框
這裏寫圖片描述
這裏寫圖片描述
10.事件過濾器
有時候,對象需要查看、甚至要攔截髮送到另外對象的事件。例如,對話框可能想要攔截按鍵事件,不讓別的組件接收到;或者要修改回車鍵的默認處理。
QObject有一個eventFilter()函數,用於建立事件過濾器。

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );

事件過濾器:它會檢查接收到的事件。如果這個事件是我們感興趣的類型,就進行我們自己的處理;如果不是,就繼續轉發。
eventFilter()函數相當於創建了過濾器,然後我們需要安裝這個過濾器。安裝過濾器需要調用QObject::installEventFilter()函數。

void QObject::installEventFilter ( QObject * filterObj )

這個函數接受一個QObject *類型的參數。我們可以向一個對象上面安裝多個事件處理器,只要調用多次installEventFilter()函數。如果一個對象存在多個事件過濾器,那麼,最後一個安裝的會第一個執行,也就是後進先執行的順序。
事件過濾器的強大之處在於,我們可以爲整個應用程序添加一個事件過濾器。installEventFilter()函數是QObject的函數,QApplication或者QCoreApplication對象都是QObject的子類,因此,我們可以向QApplication或者QCoreApplication添加事件過濾器。這種全局的事件過濾器將會在所有其它特性對象的事件過濾器之前調用。儘管很強大,但這種行爲會嚴重降低整個應用程序的事件分發效率。因此,除非是不得不使用的情況,否則的話我們不應該這麼做。

注意,如果你在事件過濾器中 delete 了某個接收組件,務必將函數返回值設爲 true。否則,Qt 還是會將事件分發給這個接收組件,從而導致程序崩潰。
事件過濾器和被安裝過濾器的組件必須在同一線程,否則,過濾器將不起作用。另外,如果在安裝過濾器之後,這兩個組件到了不同的線程,那麼,只有等到二者重新回到同一線程的時候過濾器纔會有效
11.菜單欄、工具欄和狀態欄
在實際開發過程中,QMainWindow通常只作爲“主窗口”,對話框窗口則更多地使用QDialog類。QDialog類會缺少一些QMainWindow類提供方便的函數,比如menuBar()以及toolBar()。
(1)使用menuBar()函數創建了一個菜單欄。menuBar()是QMainWindow提供的函數,這個函數會返回窗口的菜單欄,如果沒有菜單欄則會新創建一個。
(2)使用的是addToolBar()函數添加新的工具欄。
(3)statusBar()函數添加一個狀態欄。
12.佈局管理器
所謂 GUI 界面,歸根結底,就是一堆組件的疊加。我們創建一個窗口,把按鈕放上面,把圖標放上面,這樣就成了一個界面。在放置時,組件的位置尤其重要。我們必須要指定組件放在哪裏,以便窗口能夠按照我們需要的方式進行渲染。這就涉及到組件定位的機制。Qt 提供了兩種組件定位機制:絕對定位和佈局定位。
絕對定位:就是一種最原始的定位方法,給出這個組件的座標和長寬值。
<3>沒事的時候會在牛客網上找點編程題做做,鍛鍊自己的代碼邏輯,公司的代碼也在看
未來兩週計劃:
繼續學習網絡、操作系統方面的知識,看看前端的知識。

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