C++程序操作文件對話框的方法
在C++程序中有時需要通過系統(tǒng)的文件對話框去操作文件或者文件夾,我們有必要熟練掌握操作文件對話框的細節(jié),去更好的為我們軟件服務(wù)。本文我們就來講述一下C++在操作文件夾對話框的相關(guān)細節(jié),給大家借鑒和參考。
1、調(diào)用GetOpenFileName接口啟動打開文件對話框
當(dāng)我們需要使用文件對話框打開一個文件時,我們可以調(diào)用系統(tǒng)API函數(shù)GetOpenFileName來啟動系統(tǒng)的打開文件對話框。調(diào)用該API函數(shù)時需要傳入OPENFILENAME結(jié)構(gòu)體對象,通過該結(jié)構(gòu)體給打開文件對話框設(shè)置一些屬性參數(shù)。
1.1、OPENFILENAME結(jié)構(gòu)體說明
結(jié)構(gòu)體OPENFILENAME的定義有兩個版本,一個Unicode版本的OPENFILENAMEW,一個ANSI版本的OPENFILENAMEA,這個地方我們以Unicode版本的OPENFILENAMEW來說明,該結(jié)構(gòu)體的定義如下:
typedef struct tagOFNW { DWORDlStructSize; HWND hwndOwner; HINSTANCEhInstance; LPCWSTR lpstrFilter; LPWSTR lpstrCustomFilter; DWORDnMaxCustFilter; DWORDnFilterIndex; LPWSTR lpstrFile; DWORDnMaxFile; LPWSTR lpstrFileTitle; DWORDnMaxFileTitle; LPCWSTR lpstrInitialDir; LPCWSTR lpstrTitle; DWORDFlags; WORD nFileOffset; WORD nFileExtension; LPCWSTR lpstrDefExt; LPARAM lCustData; LPOFNHOOKPROC lpfnHook; LPCWSTR lpTemplateName; #ifdef _MAC LPEDITMENU lpEditInfo; LPCSTR lpstrPrompt; #endif #if (_WIN32_WINNT >= 0x0500) void *pvReserved; DWORDdwReserved; DWORDFlagsEx; #endif // (_WIN32_WINNT >= 0x0500) } OPENFILENAMEW, *LPOPENFILENAMEW;
這個地方我們講一下幾個我們使用到的字段:
- lStructSize字段[in]:用來存放當(dāng)前結(jié)構(gòu)體的長度。
- hwndOwner字段[in]:用來指定文件對話框的父窗口。
- lpstrFilter字段[in]:用來設(shè)置選擇的文件類型,如果要選擇所有文件,則設(shè)置“All Files(*.*)\0*.*\0\0”;如果選擇的是常用的圖片文件,則可以設(shè)置“圖片文件(*.bmp;*.jpg;*.jpeg;*.gif;*.png)\0*.bmp;*.jpg;*.jpeg;*.gif;*.png\0\0”。
- lpstrFile字段[out]:該字段用來傳出用戶選擇的文件信息,存放選擇的文件信息的buffer是需要外部申請內(nèi)存的,然后將buffer地址賦值給該字段,然后在GetOpenFileName調(diào)用完成后通過該字段指定的buffer輸出用戶選擇的文件信息。
- nMaxFile字段[in]:用來指定設(shè)置給lpstrFile字段對應(yīng)的buffer長度的。
- lpstrInitialDir字段[in]:用來指定打開文件對話框時的初始顯示路徑。
- Flags字段[in]:用來設(shè)定文件對話框支持的屬性,比如支持多選的OFN_ALLOWMULTISELECT、選擇的文件必須存在OFN_FILEMUSTEXIST等。
1.2、設(shè)置支持文件多選,控制選擇文件的個數(shù)上限
要支持文件多選,需要給OPENFILENAME結(jié)構(gòu)體的Flags字段添加OFN_ALLOWMULTISELECT選項。如果要控制選擇文件的個數(shù)上限,比如我們在IM聊天框中限制用戶插入圖片的個數(shù)(比如我們此處限制為5個圖片文件):
我可以在給OPENFILENAME結(jié)構(gòu)體參數(shù)設(shè)置lpstrFilter字段指定接收用戶選擇信息時指定buffer的長度最多存放5張圖片的路徑。
如果選擇多個文件時的文件信息超過buffer的長度,則GetOpenFileName會返回失敗,此時可以調(diào)用CommDlgExtendedError獲取錯誤碼,如果錯誤碼是FNERR_BUFFERTOOSMALL,則表示buffer太小存不下選擇的多個圖片文件信息,此時可以彈出提示框,相關(guān)代碼如下:
// 設(shè)置最多選擇5個文件的buffer長度 int nBufLen = 5*(MAX_PATH+1) + 1; TCHAR* pBuf = new TCHAR[nBufLen]; memset( pBuf, 0, nBufLen*sizeof(TCHAR) ); OPENFILENAME ofn; memset( &ofn, 0 ,sizeof(ofn) ); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = m_hParentWnd; ofn.lpstrFile = pBuf; ofn.nMaxFile = nBufLen; ofn.lpstrFilter = _T("All Files(*.*)\0*.*\0\0"); ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_EXPLORER|OFN_ALLOWMULTISELECT|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; // 打開文件打開對話框 BOOL bRet = ::GetOpenFileName( &ofn ); if ( !bRet ) { // 上面的ofn.lpstrFile buffer的長度設(shè)置存放3個圖片路徑,選擇較多文件時 // 會超出給定的buffer長度,所以此處要判斷一下這樣的情況,并給出提示5 DWORD dwErr = CommDlgExtendedError(); if ( dwErr == FNERR_BUFFERTOOSMALL ) { // FNERR_BUFFERTOOSMALL - The buffer pointed to by the lpstrFile member // of the OPENFILENAME structure is too small ::MessageBox( NULL, _T("最多只允許選擇5個文件,請重新選擇"), _T("提示"), MB_OK ); } delete []pBuf; return; } // 再檢查一下用戶選擇的文件個數(shù),檢測是否達到上限 int nPicTotal = 0; UIPOSITION pos = (UIPOSITION)ofn.lpstrFile; while ( pos != NULL ) { // 獲取用戶選擇的每個文件的路徑,此處可以將文件的路徑保存下來 strPicPath = GetNextPathName( pos, ofn ); ++nPicTotal; } if ( nPicTotal > 5 ) { ::MessageBox( NULL, _T("最多只允許選擇5個文件,請重新選擇"), _T("提示"), MB_OK ); delete []pBuf; return; }
當(dāng)然,我們僅僅通過FNERR_BUFFERTOOSMALL錯誤判斷文件個數(shù)超限了,是不夠的??赡苡脩暨x擇了6個文件時,總的buffer不會超限,所以還要在解析出來用戶選擇的每個文件后計算一下選擇的文件個數(shù)。
1.3、從OPENFILENAME結(jié)構(gòu)體的lpstrFile字段解析出用戶選擇的文件的完整路徑
上面我們講了,用戶在選擇完多個文件后,點擊確定,API函數(shù)GetOpenFileName返回,傳給該API函數(shù)的OPENFILENAME結(jié)構(gòu)體對象參數(shù)的lpstrFile字段中存放這用戶選擇的文件信息,比如我選擇了3個文件(docker.png、linux.png、running.png),lpstrFile中存放的數(shù)據(jù)格式會是:
C:\Users\Administrator\Desktop\CSDN文章圖集\docker.png\0linux.png\0running.png
因為這段字串中包含\0,所以我們不能把lpstrFile當(dāng)成字符串來處理。我們專門封裝了接口GetNextPathName,該接口負責(zé)將每個文件的完整路徑解析:
// 主要用于文件打開對話框選中多個文件時,解析出多個文件名(絕對路徑),從MFC庫中的CFileDialog類的GetNextPathName函數(shù)中剝離出來的 CUIString GetNextPathName( UIPOSITION& pos, OPENFILENAME& ofn ) { BOOL bExplorer = ofn.Flags & OFN_EXPLORER; TCHAR chDelimiter; if ( bExplorer ) { chDelimiter = '\0'; } else { // For old-style dialog boxes, the strings are space separated and the function uses // short file names for file names with spaces. chDelimiter = ' '; } LPTSTR lpsz = (LPTSTR)pos; if ( lpsz == ofn.lpstrFile ) // first time { if ( (ofn.Flags & OFN_ALLOWMULTISELECT) == 0 ) { pos = NULL; return ofn.lpstrFile; } // find char pos after first Delimiter while( *lpsz != chDelimiter && *lpsz != '\0' ) lpsz = _tcsinc( lpsz ); lpsz = _tcsinc( lpsz ); // if single selection then return only selection if ( *lpsz == 0 ) { pos = NULL; return ofn.lpstrFile; } } CString strPath = ofn.lpstrFile; if ( !bExplorer ) { LPTSTR lpszPath = ofn.lpstrFile; while( *lpszPath != chDelimiter ) lpszPath = _tcsinc(lpszPath); strPath = strPath.Left( lpszPath - ofn.lpstrFile ); } LPTSTR lpszFileName = lpsz; CString strFileName = lpsz; // find char pos at next Delimiter while( *lpsz != chDelimiter && *lpsz != '\0' ) lpsz = _tcsinc(lpsz); if ( !bExplorer && *lpsz == '\0' ) pos = NULL; else { if ( !bExplorer ) strFileName = strFileName.Left( lpsz - lpszFileName ); lpsz = _tcsinc( lpsz ); if ( *lpsz == '\0' ) // if double terminated then done pos = NULL; else pos = (UIPOSITION)lpsz; } // only add '\\' if it is needed if ( !strPath.IsEmpty() ) { // check for last back-slash or forward slash (handles DBCS) LPCTSTR lpsz = _tcsrchr( strPath, '\\' ); if ( lpsz == NULL ) lpsz = _tcsrchr( strPath, '/' ); // if it is also the last character, then we don't need an extra if ( lpsz != NULL && (lpsz - (LPCTSTR)strPath) == strPath.GetLength()-1 ) { ASSERT( *lpsz == '\\' || *lpsz == '/' ); return strPath + strFileName; } } return strPath + '\\' + strFileName; }
我們在外部循環(huán)調(diào)用GetNextPathName函數(shù)即可:
UIPOSITION pos = (UIPOSITION)ofn.lpstrFile; while ( pos != NULL ) { // 獲取用戶選擇的每個文件的路徑,此處可以將文件的路徑保存下來 strPicPath = GetNextPathName( pos, ofn ); ++nPicTotal; }
2、調(diào)用GetSaveFileName接口啟動保存文件對話框
當(dāng)我們需要使用保存文件對話框保存一個文件時,我們可以調(diào)用系統(tǒng)API函數(shù)GetSaveFileName來啟動系統(tǒng)的保存文件對話框。調(diào)用該函數(shù)時也是傳入OPENFILENAME結(jié)構(gòu)體對象的,通過該結(jié)構(gòu)體給打開文件對話框設(shè)置一些屬性參數(shù)。
對于GetSaveFileName接口,OPENFILENAME結(jié)構(gòu)體中的lpstrFile字段的含義是不同的,此處用來設(shè)置保存文件的默認名字的。調(diào)用函數(shù)的示例代碼如下:
TCHAR szFile[3*MAX_PATH] = { 0 }; _tcscpy( szFile, strFileName ); OPENFILENAME ofn; memset( &ofn, 0 ,sizeof(ofn) ); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = NULL; ofn.lpstrFilter = _T("All Files(*.*)|0*.*||"); ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile)/sizeof(TCHAR); ofn.lpstrDefExt = (LPCTSTR)strExt; ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_EXPLORER|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_OVERWRITEPROMPT|OFN_ENABLEHOOK; ofn.lpfnHook = FileSaveAs_OFNHookProc; // 設(shè)置回調(diào)函數(shù),添加額外的處理機制if ( ::GetSaveFileName( &ofn ) ) { // 用戶最終輸入的文件名的完整路徑 CString strPathName = ofn.lpstrFile; }
在上述代碼中,我們添加了OFN_OVERWRITEPROMPT屬性,用來指定覆蓋同名文件時給出提示;我們還添加了OFN_ENABLEHOOK屬性,用來指定設(shè)置回調(diào)函數(shù),在函數(shù)中添加額外的處理機制。在本例中,我們的HOOK回調(diào)函數(shù)如下:
// 文件對話框回調(diào)函數(shù) UINT_PTR CALLBACK FileSaveAs_OFNHookProc( HWND hdlg, // handle to child dialog box UINT uiMsg, // message identifier WPARAM wParam, // message parameter LPARAM lParam // message parameter ) { if( uiMsg == WM_NOTIFY) { LPOFNOTIFY pofn = (LPOFNOTIFY)lParam; if( pofn->hdr.code == CDN_FILEOK ) { HWND hFileDlg = ::GetParent( hdlg ); // 獲取用戶選擇保存路徑 TCHAR achCurPath[MAX_PATH*3] = { 0 }; int nRet = ::SendMessage( hFileDlg, CDM_GETFOLDERPATH, sizeof(achCurPath)/sizeof(TCHAR), (LPARAM)achCurPath ); if ( nRet < 0 ) { return 0; } // 判斷當(dāng)前程序?qū)x擇的目錄是否有寫權(quán)限 BOOL bCanWrite = CanAccessFile( achCurPath, GENERIC_WRITE ); if ( !bCanWrite ) { ::MessageBox( hFileDlg, STRING_HAVE_NO_RIGHT_SAVE_FILE, STRING_TIP, MB_OK|MB_ICONWARNING ); ::SetWindowLong( hdlg, DWL_MSGRESULT, 1 ); return 1; } } } return 0; }
在HOOK回調(diào)函數(shù)中我們攔截了點擊確定的消息,判斷一下用戶當(dāng)前選擇的路徑有沒有權(quán)限保存文件。因為在Win7及以上系統(tǒng)中,如果程序沒有管理員權(quán)限,是沒有權(quán)利向C:\Windows、C:\Program Files等系統(tǒng)關(guān)鍵路徑中寫入文件的。
判斷程序是否對某個路徑有寫權(quán)限,我們封裝了專門的判斷函數(shù),如下所示:
// 將要檢測的權(quán)限GENERIC_XXXXXX傳遞給dwGenericAccessMask,可檢測對 // 文件或者文件夾的權(quán)限 BOOL CanAccessFile( CString strPath, DWORD dwGenericAccessMask ) { CString strLog; strLog.Format( _T("[CanAccessFile] strPath: %s, dwGenericAccessMask: %d"), strPath, dwGenericAccessMask ); WriteUpdateLog( strLog ); DWORD dwSize = 0; PSECURITY_DESCRIPTOR psd = NULL; SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; WriteLog( _T("[CanAccessFile] GetFileSecurity - NULL") ); // 獲取文件權(quán)限信息結(jié)構(gòu)體大小 BOOL bRet = GetFileSecurity( strPath, si, psd, 0, &dwSize ); if ( bRet || GetLastError() != ERROR_INSUFFICIENT_BUFFER ) { strLog.Format( _T("[CanAccessFile] GetFileSecurity - NULL failed, GetLastError: %d"), GetLastError() ); WriteLog( strLog ); return FALSE; } char* pBuf = new char[dwSize]; ZeroMemory( pBuf, dwSize ); psd = (PSECURITY_DESCRIPTOR)pBuf; strLog.Format( _T("[CanAccessFile] GetFileSecurity - dwSize: %d"), dwSize ); WriteLog( strLog ); // 獲取文件權(quán)限信息結(jié)構(gòu)體大小 bRet = GetFileSecurity( strPath, si, psd, dwSize, &dwSize ); if ( !bRet ) { strLog.Format( _T("[CanAccessFile] GetFileSecurity - dwSize failed, GetLastError: %d"), GetLastError() ); WriteLog( strLog ); delete []pBuf; return FALSE; } WriteLog( _T("[CanAccessFile] OpenProcessToken") ); HANDLE hToken = NULL; if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken ) ) { strLog.Format( _T("[CanAccessFile] OpenProcessToken failed, GetLastError: %d"), GetLastError() ); WriteLog( strLog ); delete []pBuf; return FALSE; } WriteLog( _T("[CanAccessFile] DuplicateToken") ); // 模擬令牌 HANDLE hImpersonatedToken = NULL; if( !DuplicateToken( hToken, SecurityImpersonation, &hImpersonatedToken ) ) { strLog.Format( _T("[CanAccessFile] DuplicateToken failed, GetLastError: %d"), GetLastError() ); WriteLog( strLog ); delete []pBuf; CloseHandle( hToken ); return FALSE; } WriteLog( _T("[CanAccessFile] MapGenericMask") ); // 在檢測是否有某個權(quán)限時,將GENERIC_WRITE等值傳給本函數(shù)的第二個參數(shù)dwGenericAccessMask // GENERIC_WRITE等參數(shù)在調(diào)用CreateFile創(chuàng)建文件時會使用到,下面調(diào)用MapGenericMask將 // GENERIC_WRITE等轉(zhuǎn)換成FILE_GENERIC_WRITE等 // 將GENERIC_XXXXXX轉(zhuǎn)換成FILE_GENERIC_XXXXXX GENERIC_MAPPING genMap; genMap.GenericRead = FILE_GENERIC_READ; genMap.GenericWrite = FILE_GENERIC_WRITE; genMap.GenericExecute = FILE_GENERIC_EXECUTE; genMap.GenericAll = FILE_ALL_ACCESS; MapGenericMask( &dwGenericAccessMask, &genMap ); WriteLog( _T("[CanAccessFile] AccessCheck") ); // 調(diào)用AccessCheck來檢測是否有指定的權(quán)限 PRIVILEGE_SET privileges = { 0 }; DWORD dwGrantedAccess = 0; DWORD privLength = sizeof(privileges); BOOL bGrantedAccess = FALSE; if( AccessCheck( psd, hImpersonatedToken, dwGenericAccessMask, &genMap, &privileges, &privLength, &dwGrantedAccess, &bGrantedAccess ) ) { strLog.Format( _T("[CanAccessFile] AccessCheck succeed, dwGenericAccessMask: %d, dwGrantedAccess: %d, bGrantedAccess: %d, "), dwGenericAccessMask, dwGrantedAccess, bGrantedAccess ); WriteLog( strLog ); if ( bGrantedAccess ) { if ( dwGenericAccessMask == dwGrantedAccess ) { bGrantedAccess = TRUE; } else { bGrantedAccess = FALSE; } } else { bGrantedAccess = FALSE; } } else { strLog.Format( _T("[CanAccessFile] AccessCheck failed, GetLastError: %d"), GetLastError() ); WriteLog( strLog ); bGrantedAccess = FALSE; } strLog.Format( _T("[CanAccessFile] bGrantedAccess: %d"), bGrantedAccess ); WriteLog( strLog ); delete []pBuf; CloseHandle( hImpersonatedToken ); CloseHandle( hToken ); return bGrantedAccess; }
另外,我們可以在HOOK回調(diào)函數(shù)中調(diào)整文件對話框相對于父窗口的彈出位置,攔截WM_INITDIALOG消息,代碼如下:
// 通過該回調(diào)函數(shù)移動文件保存對話框的位置,解決win32 文件對話框默認顯示在屏幕左上方的問題 UINT_PTR CALLBACK OFNHookProc( HWND hdlg, // handle to child dialog box UINT uiMsg, // message identifier WPARAM wParam, // message parameter LPARAM lParam // message parameter ) { if ( uiMsg == WM_INITDIALOG ) { HWND hFileDlg = ::GetParent( hdlg ); HWND hParent = ::GetParent( hFileDlg ); RECT rcParent; ::GetWindowRect( hParent, &rcParent ); RECT rcFileDlg; ::GetWindowRect( hFileDlg, &rcFileDlg ); int nFileDlgWdith = rcFileDlg.right - rcFileDlg.left; int nFileDlgHeight = rcFileDlg.bottom - rcFileDlg.top; RECT rcDst; rcDst.left = rcParent.left + ( (rcParent.right - rcParent.left) - nFileDlgWdith )/2; rcDst.right = rcDst.left + nFileDlgWdith; rcDst.bottom = rcParent.bottom + 1; rcDst.top = rcDst.bottom - nFileDlgHeight; // 下面保證文件對話框處于屏幕可視區(qū)域內(nèi) if ( rcDst.left < 0 ) { rcDst.left = 0; rcDst.right = rcDst.left + nFileDlgWdith; } if ( rcDst.top < 0 ) { rcDst.top = 0; rcDst.bottom = rcDst.top + nFileDlgHeight; } int nXScreen = ::GetSystemMetrics( SM_CXSCREEN ); int nYScreen = ::GetSystemMetrics( SM_CYSCREEN ); if ( rcDst.right > nXScreen ) { rcDst.right = nXScreen; rcDst.left = rcDst.right - nFileDlgWdith; } if ( rcDst.bottom > nYScreen ) { rcDst.bottom = nYScreen; rcDst.top = rcDst.bottom - nFileDlgHeight; } // 重新設(shè)置文件對話框位置 ::SetWindowPos( hFileDlg, NULL, rcDst.left, rcDst.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER ); return 1; } return 0; }
3、調(diào)用SHBrowseForFolder接口打開瀏覽文件夾對話框
當(dāng)我們在IM聊天框中發(fā)起文件傳輸時,我們要發(fā)送的是一個文件夾,可能就需要使用到系統(tǒng)的瀏覽文件夾對話框來選擇要發(fā)送的文件夾。當(dāng)我們在接收到多個文件時,可以選擇全部另存為,此時也需要使用系統(tǒng)的瀏覽文件夾對話框來選擇要另存為的路徑。
我們調(diào)用SHBrowseForFolder接口即可打開瀏覽文件夾對話框,相關(guān)代碼如下所示:
// 打開目錄選擇對話框 ::CoInitialize( NULL ); LPMALLOC lpMalloc = NULL; TCHAR pchSelDir[MAX_PATH] = {0}; pchSelDir[0] = _T('\0'); if( E_FAIL == ::SHGetMalloc(&lpMalloc) ) { ::CoUninitialize(); return; } BROWSEINFO browseInfo; browseInfo.hwndOwner = m_hParentWnd; browseInfo.pidlRoot = NULL; browseInfo.pszDisplayName = NULL; browseInfo.lpszTitle = STRING_SEL_FOLDER_TO_SEND; browseInfo.ulFlags= BIF_RETURNONLYFSDIRS; browseInfo.lpfn = NULL; browseInfo.lParam = 0; // 打開瀏覽文件夾對話框 LPITEMIDLIST lpItemIDList = NULL; if ( ( lpItemIDList = ::SHBrowseForFolder(&browseInfo) ) != NULL ) { // 獲取用戶選擇的文件夾 ::SHGetPathFromIDList( lpItemIDList, pchSelDir ); lpMalloc->Free( lpItemIDList ); lpMalloc->Release(); } else { lpMalloc->Free( lpItemIDList ); lpMalloc->Release(); ::CoUninitialize(); return; } ::CoUninitialize();
4、最后
到此這篇關(guān)于C++如何操作文件對話框的文章就介紹到這了,更多相關(guān)C++文件對話框內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解C++值多態(tài)中的傳統(tǒng)多態(tài)與類型擦除
值多態(tài)是一種介于傳統(tǒng)多態(tài)與類型擦除之間的多態(tài)實現(xiàn)方式,借鑒了值語義,保留了繼承,在單繼承的適用范圍內(nèi),程序和程序員都能從中受益。這篇文章主要介紹了C++值多態(tài)中的傳統(tǒng)多態(tài)與類型擦除,需要的朋友可以參考下2020-04-04C語言之?dāng)?shù)組名與數(shù)組起始地址的關(guān)系解析
這篇文章主要介紹了C語言之?dāng)?shù)組名與數(shù)組起始地址的關(guān)系,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07C++中可以接受任意多個參數(shù)的函數(shù)定義方法(詳解)
下面小編就為大家?guī)硪黄狢++中可以接受任意多個參數(shù)的函數(shù)定義方法(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10