首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 類成員初始化列表詳解與 MFC 應用中添加「位置欄」

     編輯:關於C++

C++ 類成員初始化:賦值與初始化列表的差異

在 C++ 開發中,類成員的初始化方式主要有兩種:在建構函式主體內賦值,以及使用成員初始化列表。雖然兩者在許多情況下效果相同,但初始化列表在某些場景下是必要的,且通常更高效。

何時必須使用初始化列表

當成員物件本身是類別或結構,且只有帶參數的建構函式(沒有預設建構函式)時,必須使用初始化列表。例如:

class CMember {
public:
    CMember(int x) { /* ... */ }
};

此時無法先建立 CMember 實例再賦值,必須在外層類別的建構函式中直接傳遞參數:

class CMyClass {
    CMember m_member;
public:
    CMyClass();
};

CMyClass::CMyClass() : m_member(2) { }

同理,const 成員與參考成員也只能在初始化列表中設定初值,因為它們不允許事後賦值。

效率考量:避免雙重建構與賦值

以 MFC 的 CString 為例,若在建構函式主體賦值:

CMyClass::CMyClass() {
    m_str = _T("yada yada"); // 先預設建構,再呼叫 operator=
}

編譯器會先生成 CString 的預設建構函式呼叫,再執行賦值運算子,共兩次函式呼叫。改用初始化列表:

CMyClass::CMyClass() : m_str(_T("yada yada")) { }

則直接呼叫帶參數的建構函式,僅一次呼叫。對於內建型別(int、long 等)兩者無性能差異,但養成使用初始化列表的習慣可提升程式碼一致性與可維護性。

初始化順序陷阱

成員初始化順序依宣告順序,而非初始化列表中的書寫順序。錯誤範例:

class CMyClass {
    int m_x, m_y;
public:
    CMyClass(int i) : m_y(i), m_x(m_y) { } // 危險:m_x 先被初始化,取得未定義的 m_y
};

解決方法:調整宣告順序,或確保初始化列表順序與宣告順序一致。


在 MFC 應用程式中啟用 Windows 2000 風格的「位置欄」

Windows 2000 引入了新版 commdlg.dll,提供帶有「位置欄」的開啟檔案對話框。MFC 應用若直接使用 CFileDialog,預設仍顯示舊版對話框,原因在於 MFC 內部使用 Hook 機制整合訊息對應,導致系統判斷為舊版應用而回退舊 UI。

核心問題分析

  • OPENFILENAME 結構在 _WIN32_WINNT >= 0x0500 時新增三個欄位(pvReserved、dwReserved、FlagsEx)。
  • 系統依 lStructSize 判斷新舊版本,但 MFC 靜態連結或使用舊版 DLL 時,結構大小固定為舊版。
  • 關鍵發現:Windows 2000 會檢查 OFN_ENABLEHOOK 標誌。若設定(MFC 預設會設定),則強制使用舊版對話框。

解決方案

繞過 CFileDialog,直接呼叫 GetOpenFileName 且不設定 Hook。範例:

void CMyApp::OnFileOpen() {
    OPENFILENAME ofn = {0};
    ofn.lStructSize = sizeof(ofn); // 使用舊版 SDK 編譯時為舊大小
    ofn.hwndOwner = m_pMainWnd->GetSafeHwnd();
    ofn.lpstrFilter = _T("所有檔案\0*.*\0");
    ofn.nFilterIndex = 1;
    ofn.lpstrFile = new TCHAR[MAX_PATH];
    ofn.lpstrFile[0] = _T('\0');
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST; // 不設 OFN_ENABLEHOOK

    if (::GetOpenFileName(&ofn)) {
        // 使用者選取檔案
    }
    delete[] ofn.lpstrFile;
}

此法在 Windows 9x/NT 顯示舊對話框,在 Windows 2000 以上自動顯示新版「位置欄」對話框,完美相容。

未來展望

微軟後續版本的 Visual C++ 將提供支援新 UI 的 MFC DLL(不同檔名),屆時可直接使用 CFileDialog 享受新功能。在此之前,直接呼叫 API 是最穩健的選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved