乘風破浪,遇見最美Windows 11之現代Windows桌面應用開發 - 使用C++創建Windows桌面應用程序


什么是C++中的Windows桌面應用程序

https://learn.microsoft.com/zh-cn/cpp/windows/desktop-applications-visual-cpp

用C++編寫的桌面應用程序是一個本地應用程序,它可以訪問全套的Windows API,並在窗口或系統控制台中運行。用C++編寫的桌面應用程序可以在Windows XP到Windows 11上運行(盡管Windows XP已不再得到官方支持,而且有許多Windows API是在那之后引入的)。

桌面應用程序與通用Windows平台(UWP)應用程序不同,后者可以在運行Windows 11、Windows 10、XBox、Windows Phone、Surface Hub和其他設備的PC上運行。

什么是Windows API

https://docs.microsoft.com/zh-cn/cpp/windows/walkthrough-creating-windows-desktop-applications-cpp

Windows API(也被稱為Win32 API、Windows桌面API和Windows經典API)是一個基於C語言的框架,用於創建Windows應用程序。它自20世紀80年代以來一直存在,幾十年來一直被用來創建Windows應用程序。更高級和更容易編程的框架已經建立在Windows API之上,例如,MFC、ATL、.NET框架。 即使是用C++/WinRT編寫的UWP和Store應用程序的最現代的Windows Runtime代碼也使用Windows API的底層。

先決條件

  • 一台運行微軟Windows 7或更高版本的計算機。我們建議使用Windows 10或更高版本以獲得最佳的開發體驗。

  • 一份Visual Studio的拷貝。關於如何下載和安裝Visual Studio的信息,請參見安裝Visual Studio。當你運行安裝程序時,確保勾選了用C++進行桌面開發(Desktop development with C++) 的工作負載。如果你在安裝Visual Studio時沒有安裝這個工作負載,不要擔心。你可以再次運行安裝程序,現在就安裝它。

image

Visual Studio安裝程序中使用C++的桌面開發工作負載的細節。

  • 了解使用Visual Studio IDE的基本知識。如果你以前使用過Windows桌面應用程序,你可能可以跟上。有關介紹,請參見Visual Studio IDE功能之旅

  • 對C++語言的基礎知識有足夠的了解,可以跟着學。別擔心,我們不會做太復雜的事情。

創建一個Windows桌面項目

https://github.com/TaylorShi/DemoForCppDesktop

按照這些步驟來創建你的第一個Windows桌面項目。在你進行的過程中,你將為一個工作的Windows桌面應用程序輸入代碼。要查看你喜歡的Visual Studio版本的文檔,請使用版本選擇器控件。它位於本頁面目錄的頂部

要在Visual Studio中創建一個Windows桌面項目

  1. 在主菜單中,選擇"文件(File)">"新建(New)">"項目(Project)",打開"創建新項目(Create a New Project)"的對話框。

image

image

  1. 在對話框的頂部,將"語言(Language)"設置為"C++",將"平台(Platform)"設置為"Windows",並將"項目類型(Project type)"設置為"桌面(Desktop)"。

image

  1. 從過濾后的項目類型列表中,選擇"Windows桌面向導(Windows Desktop Wizard)",然后選擇"下一步(Next)"。在下一頁,為項目輸入一個名稱,例如,"DemoForCppDesktop"。

image

  1. 選擇"創建(Create)"按鈕來創建項目。

image

  1. 現在出現"Windows桌面項目(Windows Desktop Project)"對話框。在"應用程序類型(Application type)"下,選擇"桌面應用程序(Desktop application)(.exe)"。在"其他選項(Additional options)"下,選擇"空項目(Empty project)"。選擇"確定(OK)"來創建這個項目。

image

image

  1. 在"解決方案資源管理器(Solution Explorer)"中,右鍵單擊"DemoForCppDesktop"項目,選擇"添加(Add)",然后選擇"新建項(New Item)"。

image

  1. 在"添加新項(Add New Item)"對話框中,選擇"C++文件(C++ File)(.cpp)"。在"名稱(Name)"框中,鍵入一個文件名,例如,HelloWindowsDesktop.cpp。選擇"添加(Add)"。

image

image

現在你的項目已經創建,你的源文件在編輯器中被打開。要繼續,請跳到創建代碼。

創建代碼

接下來,你將學習如何在Visual Studio中創建一個Windows桌面應用程序的代碼。

要啟動一個Windows桌面應用程序

  1. 就像每個C語言程序和C++程序都必須有一個main函數作為其起點一樣,每個Windows桌面程序都必須有一個WinMain函數。WinMain的語法如下。
int WINAPI WinMain(
   _In_ HINSTANCE hInstance,
   _In_opt_ HINSTANCE hPrevInstance,
   _In_ LPSTR     lpCmdLine,
   _In_ int       nCmdShow
);

image

有關該函數的參數和返回值的信息,見WinMain入口點

所有這些額外的詞,如WINAPI,或CALLBACK,或HINSTANCE,或_In_,都是什么?傳統的Windows API廣泛使用類型化定義和預處理器宏來抽象出類型和平台特定代碼的一些細節,如調用約定、__declspec聲明和編譯器語義。在Visual Studio中,你可以使用IntelliSense快速信息功能來查看這些類型定義和宏的定義。將鼠標懸停在感興趣的詞上,或者選擇它並按下Ctrl+KCtrl+I,就會彈出一個包含定義的小窗口。欲了解更多信息,請參見使用智能提示。參數和返回類型經常使用SAL注釋來幫助你發現編程錯誤。欲了解更多信息,請參閱使用SAL注釋來減少C/C++代碼缺陷

  1. Windows桌面程序需要<windows.h>.<tchar.h>定義了TCHAR宏,如果你的項目中定義了UNICODE符號,它最終會解析為wchar_t,否則會解析為char。如果你總是在啟用UNICODE的情況下構建,你就不需要TCHAR,可以直接使用wchar_t
#include <windows.h>
#include <tchar.h>
  1. 除了WinMain函數外,每個Windows桌面應用程序還必須有一個窗口程序函數。這個函數通常被命名為WndProc,但你可以隨心所欲地命名它。WndProc的語法如下。
LRESULT CALLBACK WndProc(
   _In_ HWND   hWnd,
   _In_ UINT   message,
   _In_ WPARAM wParam,
   _In_ LPARAM lParam
);

image

在這個函數中,你寫代碼來處理事件發生時應用程序從Windows收到的消息。例如,如果用戶在你的應用程序中選擇了一個OK按鈕,Windows將向你發送一條消息,你可以在WndProc函數中編寫代碼,做任何適當的工作。這就是所謂的處理一個事件。你只處理與你的應用程序有關的事件。

欲了解更多信息,請參見窗口程序

為了給WinMain函數增加功能

  1. WinMain函數中,你填充了一個WNDCLASSEX類型的結構。該結構包含關於窗口的信息:應用程序的圖標、窗口的背景顏色、顯示在標題欄中的名稱,以及其他一些東西。重要的是,它包含一個指向你的窗口程序的函數指針。下面的例子顯示了一個典型的WNDCLASSEX結構。
WNDCLASSEX wcex;

wcex.cbSize         = sizeof(WNDCLASSEX);
wcex.style          = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc    = WndProc;
wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = 0;
wcex.hInstance      = hInstance;
wcex.hIcon          = LoadIcon(wcex.hInstance, IDI_APPLICATION);
wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName   = NULL;
wcex.lpszClassName  = szWindowClass;
wcex.hIconSm        = LoadIcon(wcex.hInstance, IDI_APPLICATION);

關於上述結構的字段信息,見WNDCLASSEX

  1. 向Windows注冊WNDCLASSEX,這樣它就知道你的窗口以及如何向它發送消息。使用RegisterClassEx函數,並將窗口類結構作為參數傳遞。使用_T宏,因為我們使用TCHAR類型。
if (!RegisterClassEx(&wcex))
{
   MessageBox(NULL,
      _T("Call to RegisterClassEx failed!"),
      _T("Windows Desktop Guided Tour"),
      NULL);

   return 1;
}
  1. 現在你可以創建一個窗口。使用CreateWindowEx函數。
static TCHAR szWindowClass[] = _T("DesktopApp");
static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");

// The parameters to CreateWindowEx explained:
// WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindowEx(
WS_EX_OVERLAPPEDWINDOW,
   szWindowClass,
   szTitle,
   WS_OVERLAPPEDWINDOW,
   CW_USEDEFAULT, CW_USEDEFAULT,
   500, 100,
   NULL,
   NULL,
   hInstance,
   NULL
);
if (!hWnd)
{
   MessageBox(NULL,
      _T("Call to CreateWindowEx failed!"),
      _T("Windows Desktop Guided Tour"),
      NULL);

   return 1;
}

這個函數返回一個HWND,它是一個窗口的句柄。一個句柄有點像一個指針,Windows用它來跟蹤打開的窗口。欲了解更多信息,請參見Windows數據類型

  1. 在這一點上,窗口已經被創建,但我們仍然需要告訴Windows使其可見。這就是這段代碼的作用:
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
   nCmdShow);
UpdateWindow(hWnd);

顯示的窗口沒有什么內容,因為你還沒有實現WndProc函數。換句話說,應用程序還沒有處理Windows現在向它發送的信息。

  1. 為了處理這些消息,我們首先添加一個消息循環來監聽Windows發送的消息。當應用程序收到一個消息時,這個循環將其分派給你的WndProc函數來處理。該消息循環類似於以下代碼。
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
   TranslateMessage(&msg);
   DispatchMessage(&msg);
}

return (int) msg.wParam;

關於消息循環中的結構和函數的更多信息,請參見MSG, GetMessage, TranslateMessage, 和DispatchMessage

在這一點上,WinMain函數應該類似於以下代碼。

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
   WNDCLASSEX wcex;

   wcex.cbSize = sizeof(WNDCLASSEX);
   wcex.style          = CS_HREDRAW | CS_VREDRAW;
   wcex.lpfnWndProc    = WndProc;
   wcex.cbClsExtra     = 0;
   wcex.cbWndExtra     = 0;
   wcex.hInstance      = hInstance;
   wcex.hIcon          = LoadIcon(wcex.hInstance, IDI_APPLICATION);
   wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
   wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
   wcex.lpszMenuName   = NULL;
   wcex.lpszClassName  = szWindowClass;
   wcex.hIconSm        = LoadIcon(wcex.hInstance, IDI_APPLICATION);

   if (!RegisterClassEx(&wcex))
   {
      MessageBox(NULL,
         _T("Call to RegisterClassEx failed!"),
         _T("Windows Desktop Guided Tour"),
         NULL);

      return 1;
   }

   // Store instance handle in our global variable
   hInst = hInstance;

   // The parameters to CreateWindowEx explained:
   // WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
   // szWindowClass: the name of the application
   // szTitle: the text that appears in the title bar
   // WS_OVERLAPPEDWINDOW: the type of window to create
   // CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
   // 500, 100: initial size (width, length)
   // NULL: the parent of this window
   // NULL: this application dows not have a menu bar
   // hInstance: the first parameter from WinMain
   // NULL: not used in this application
   HWND hWnd = CreateWindowEx(
      WS_EX_OVERLAPPEDWINDOW,
      szWindowClass,
      szTitle,
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, CW_USEDEFAULT,
      500, 100,
      NULL,
      NULL,
      hInstance,
      NULL
   );

   if (!hWnd)
   {
      MessageBox(NULL,
         _T("Call to CreateWindow failed!"),
         _T("Windows Desktop Guided Tour"),
         NULL);

      return 1;
   }

   // The parameters to ShowWindow explained:
   // hWnd: the value returned from CreateWindow
   // nCmdShow: the fourth parameter from WinMain
   ShowWindow(hWnd,
      nCmdShow);
   UpdateWindow(hWnd);

   // Main message loop:
   MSG msg;
   while (GetMessage(&msg, NULL, 0, 0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }

   return (int) msg.wParam;
}

為了給WndProc函數增加功能

  1. 為了使WndProc函數能夠處理應用程序收到的消息,實現一個switch語句。

要處理的一個重要消息是WM_PAINT消息。當其顯示的窗口的一部分必須被更新時,應用程序就會收到WM_PAINT消息。當用戶把一個窗口移到你的窗口前面,然后又把它移開,這個事件就會發生。你的應用程序不知道這些事件何時發生。只有Windows知道,所以它用WM_PAINT消息來通知你的應用程序。當窗口第一次被顯示時,所有的窗口都必須被更新。

要處理一個WM_PAINT消息,首先要調用BeginPaint,然后處理所有的邏輯來布置窗口中的文本、按鈕和其他控件,然后調用EndPaint。對於應用程序來說,在開始調用和結束調用之間的邏輯在窗口中顯示字符串 "你好,Windows桌面!"。在下面的代碼中,TextOut函數被用來顯示這個字符串。

PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hello, Windows desktop!");

switch (message)
{
case WM_PAINT:
   hdc = BeginPaint(hWnd, &ps);

   // Here your application is laid out.
   // For this introduction, we just print out "Hello, Windows desktop!"
   // in the top left corner.
   TextOut(hdc,
      5, 5,
      greeting, _tcslen(greeting));
   // End application-specific layout section.

   EndPaint(hWnd, &ps);
   break;
}

代碼中的HDC是一個設備上下文的句柄,用於在窗口的客戶區繪圖。使用BeginPaintEndPaint函數來准備和完成客戶端區域的繪制。BeginPaint返回用於在客戶端區域繪圖的顯示設備上下文的句柄;EndPaint結束繪圖請求並釋放設備上下文。

  1. 一個應用程序通常會處理許多其他的消息。例如,當一個窗口第一次被創建時,WM_CREATE,當窗口關閉時,WM_DESTROY。下面的代碼顯示了一個基本但完整的WndProc函數。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   HDC hdc;
   TCHAR greeting[] = _T("Hello, Windows desktop!");

   switch (message)
   {
   case WM_PAINT:
      hdc = BeginPaint(hWnd, &ps);

      // Here your application is laid out.
      // For this introduction, we just print out "Hello, Windows desktop!"
      // in the top left corner.
      TextOut(hdc,
         5, 5,
         greeting, _tcslen(greeting));
      // End application specific layout section.

      EndPaint(hWnd, &ps);
      break;
   case WM_DESTROY:
      PostQuitMessage(0);
      break;
   default:
      return DefWindowProc(hWnd, message, wParam, lParam);
      break;
   }

   return 0;
}

構建代碼

正如承諾的那樣,這里是工作程序的完整代碼。

要建立這個例子

  1. 在編輯器中刪除你在HelloWindowsDesktop.cpp中輸入的任何代碼。復制此示例代碼,然后將其粘貼到HelloWindowsDesktop.cpp中。
// HelloWindowsDesktop.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

// Global variables

// The main window class name.
static TCHAR szWindowClass[] = _T("DesktopApp");

// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");

// Stored instance handle for use in Win32 API calls such as FindResource
HINSTANCE hInst;

// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(
   _In_ HINSTANCE hInstance,
   _In_opt_ HINSTANCE hPrevInstance,
   _In_ LPSTR     lpCmdLine,
   _In_ int       nCmdShow
)
{
   WNDCLASSEX wcex;

   wcex.cbSize = sizeof(WNDCLASSEX);
   wcex.style          = CS_HREDRAW | CS_VREDRAW;
   wcex.lpfnWndProc    = WndProc;
   wcex.cbClsExtra     = 0;
   wcex.cbWndExtra     = 0;
   wcex.hInstance      = hInstance;
   wcex.hIcon          = LoadIcon(wcex.hInstance, IDI_APPLICATION);
   wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
   wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
   wcex.lpszMenuName   = NULL;
   wcex.lpszClassName  = szWindowClass;
   wcex.hIconSm        = LoadIcon(wcex.hInstance, IDI_APPLICATION);

   if (!RegisterClassEx(&wcex))
   {
      MessageBox(NULL,
         _T("Call to RegisterClassEx failed!"),
         _T("Windows Desktop Guided Tour"),
         NULL);

      return 1;
   }

   // Store instance handle in our global variable
   hInst = hInstance;

   // The parameters to CreateWindowEx explained:
   // WS_EX_OVERLAPPEDWINDOW : An optional extended window style.
   // szWindowClass: the name of the application
   // szTitle: the text that appears in the title bar
   // WS_OVERLAPPEDWINDOW: the type of window to create
   // CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
   // 500, 100: initial size (width, length)
   // NULL: the parent of this window
   // NULL: this application does not have a menu bar
   // hInstance: the first parameter from WinMain
   // NULL: not used in this application
   HWND hWnd = CreateWindowEx(
      WS_EX_OVERLAPPEDWINDOW,
      szWindowClass,
      szTitle,
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, CW_USEDEFAULT,
      500, 100,
      NULL,
      NULL,
      hInstance,
      NULL
   );

   if (!hWnd)
   {
      MessageBox(NULL,
         _T("Call to CreateWindow failed!"),
         _T("Windows Desktop Guided Tour"),
         NULL);

      return 1;
   }

   // The parameters to ShowWindow explained:
   // hWnd: the value returned from CreateWindow
   // nCmdShow: the fourth parameter from WinMain
   ShowWindow(hWnd,
      nCmdShow);
   UpdateWindow(hWnd);

   // Main message loop:
   MSG msg;
   while (GetMessage(&msg, NULL, 0, 0))
   {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }

   return (int) msg.wParam;
}

//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   HDC hdc;
   TCHAR greeting[] = _T("Hello, Windows desktop!");

   switch (message)
   {
   case WM_PAINT:
      hdc = BeginPaint(hWnd, &ps);

      // Here your application is laid out.
      // For this introduction, we just print out "Hello, Windows desktop!"
      // in the top left corner.
      TextOut(hdc,
         5, 5,
         greeting, _tcslen(greeting));
      // End application-specific layout section.

      EndPaint(hWnd, &ps);
      break;
   case WM_DESTROY:
      PostQuitMessage(0);
      break;
   default:
      return DefWindowProc(hWnd, message, wParam, lParam);
      break;
   }

   return 0;
}
  1. 在"構建(Build)"菜單上,選擇"構建解決方案(Build Solution)"。編譯的結果應該出現在Visual Studio的"輸出(Output)"窗口中。

image

  1. 要運行該應用程序,按F5。一個包含"Hello, Windows desktop!"文字的窗口應該出現在顯示屏的左上角。

image

恭喜你!你已經完成了本攻略,並建立了一個傳統的Windows桌面應用程序。你已經完成了本攻略並建立了一個傳統的Windows桌面應用程序。

通過命令行編譯本機C++程序

創建Hello.cpp

image

添加如下內容:

#include <iostream>
using namespace std;
int main()
{
    cout << "Hello, world, from Visual C++!" << endl;
}

image

通過命令行編譯Hello.cpp

cl /EHsc Hello.cpp

image

cl.exe編譯器會生成包含已編譯代碼的.obj文件,然后運行鏈接器來創建名為Hello.exe的可執行程序

執行編譯后的Hello.exe

.\Hello

image

用C++編寫第一個程序

簡介

C++旨在支持過程、面向對象的編程和泛型編程。這是一種基於編譯器的編程語言,因此經過靜態類型化且區分大小寫。C++的用法是無限的。

下面是使用C++的一些示例:

  • Web瀏覽器。C++用於創建Web瀏覽器及其插件和擴展。

  • 操作系統。C++用於構建操作系統。許多版本的Windows部分都是用C++編寫的。SymbianOS主要采用C++編寫而成。

  • 編譯器。編譯器,因為用於C#和Java等語言的編譯器都是用C++編寫的。事實上,許多C++編譯器都是用C++編寫的。

  • 媒體應用程序。C++用於創建媒體應用程序並管理音頻和視頻文件。C++用於實現實時音頻的應用程序,如有聲讀物和轉錄視頻的應用。

  • 數據庫引擎。C++已用於開發數據庫應用程序(包括MySQL)。

  • 游戲。多種動畫和游戲都需要C++才能進行建模、制作3D動畫、渲染和模擬。開發者經常用來創建游戲的游戲引擎可使用C++進行構建。

  • 醫療工程。使用醫療工程的開發者將使用C++創建更多的應用程序。C++在使用掃描技術(如MRI)的計算機中廣泛使用。C++也用於各種嵌入式系統。

  • 機器人。機器人開發者通常會使用C++來對微控制器進行編程,從而提高性能和工作效率。許多硬件庫是用C++編寫的,以便與低級別硬件進行交互。

創建hello.cpp

在C盤創建CppFirstApp目錄,使用Visual Studio Code打開它,創建一個hello.cpp文件。

#include <iostream>
using namespace std;
int main()
{
    cout << "Hello World!\n";
    return 0;
}

image

在Windows上使用MSVC編譯器編譯CPP文件

編譯器可將用某種語言編寫的源代碼轉換為另一種語言。在這里,編譯器將C++源代碼轉換為計算機代碼。計算機理解計算機代碼,並創建可執行程序

找到你的Visual Studio,它有個Developer Command Prompt for VS 2022,它本質是連接到

%comspec% /k "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat"

我們切換到CppFirstApp目錄,通過如下命令編譯

cl hello.cpp

image

c:\CppFirstApp>cl hello.cpp
用於 x86 的 Microsoft (R) C/C++ 優化編譯器 19.35.32215 版
版權所有(C) Microsoft Corporation。保留所有權利。

hello.cpp
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.35.32215\include\ostream(774): warning C4530: 使用了 C++ 異常處理程序,但未啟用展開語義。請指定 /EHsc
hello.cpp(5): note: 查看對正在編譯的函數 模板 實例化“std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char *)”的引用
Microsoft (R) Incremental Linker Version 14.35.32215.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:hello.exe
hello.obj

最終我們看到得到了hello.exehello.obj兩個文件。

.\hello.exe

這時候我們直接執行hello.exe就行了。

image

修改輸出內容

#include <iostream>
using namespace std;
int main()
{
    //cout << "Hello World!\n";
    cout << "Congratulations!";
    cout << " ";
    cout << "You wrote your first lines of code in C++.\n";
    return 0;
}

重新之前編輯並且運行。

image

這里編譯器的主要工作是將代碼轉換為計算機可以理解的可執行格式。

C++是區分大小寫的。

C++使用雙引號創建字符串字面量。

在Linux上使用G++編譯器編譯CPP文件

g++ hello.cpp && ls

image

這時候會得到一個a.out文件。

執行這個文件

./a.out

image

image

程序在C++中的工作原理

為了更好地了解上訴內容,從最上面一行開始逐行瀏覽程序語法很有幫助。

  • iostream是標准庫的一部分。程序中的許多組件都由標准庫,或者你或第三方寫入的庫定義。代碼利用標准庫的一部分iostream來使用cout對象輸出某些內容。
#include <iostream>
  • namespace命名空間有助於防止大型項目中的名稱沖突。你想要在整個代碼中使用命名空間的功能,而無需在需要時重復調用命名空間。因此,在代碼的開頭聲明命名空間。此外,使用cout所需的語法是std::cout。添加using namespace std;行后,無需重復使用std
#include <iostream>
using namespace std;
  • 函數是共同執行任務的一組語句。main()是全局函數,它是程序的指定開頭。每個C++程序都必須具有main()函數。main()之前使用的int表示此函數需要返回一個整數。
#include <iostream>
using namespace std;
int main()
{
  cout << "Hello World\n";
  return 0;
}
  • cout輸出特定字符串。std::coutstd::ostream類的數據和操作集合的一部分。
#include <iostream>
using namespace std;
int main() 
{
  cout << "Hello World\n";
  return 0;
}
  • Hello World輸出設置在雙引號("")中。可以通過多種方式使用std::string。使用std::string的主要方式有兩種,一種是作為C字符串(字符數組),一種是作為string類char是基元數據類型。

我們使用不同的數據類型(如整數、單精度浮點數、雙精度浮點數和字符)來表示和存儲值。例如,整數可能是123,單精度浮點數可能是9.02,字符可能是'a'。

#include <iostream>
using namespace std;
int main() 
{
  cout << "Hello World\n";
  return 0;
}
  • 使用\n終止字符串,並移到下一行。\n稱為“轉義序列”。
cout << "Hello World\n";

除了使用\n來換行,還可以支持使用endl操縱器。

cout << "Hello World" << endl;
  • 聲明函數int main()時,指定int以聲明返回整數的函數。如果函數前面有int,則它要求返回一個整數。因此,編寫return 0后可以確保返回一個整數來完成函數。在這里,return是關鍵字,0是整數。
#include <iostream>
using namespace std;
int main() 
{
  cout << "Hello World\n";
  return 0;
}

常見錯誤

C++時可能遇到的常見錯誤的摘要

  • 大寫字母錯誤。C++區分大小寫,大小寫很重要。如果在代碼中使用了錯誤的大小寫,則編譯器無法識別你嘗試使用的命令

  • 流運算符錯誤。使用正確的運算符非常重要。例如,識別要輸出的流或讀取信息時。

  • 引號類型錯誤。單個字符需要加單引號。多個字符的字符串字面量和字需要加雙引號。

  • 缺少分號。所有語句都需要以分號(;)結尾。

  1. 大寫字母(如大寫cout中的c或大寫return中的r)會導致錯誤。使用不正確的大小寫會導致編譯錯誤。
Return 0;  // 錯誤
return 0; // 正確
  1. 使用流運算符將流引導到兩個方向中的一個方向-從流中讀取(>>)或寫入流中(<<)。一個常見錯誤是使用了錯誤的流運算符,例如在cout中使用a >>而不是a <<
cout >> "a string"; // 錯誤
cout << "a string"; // 正確
  1. 必須記住是使用單引號還是雙引號。使用單引號('')表示單個字符,例如"Hello World"中的'H'。使用雙引號("")表示用於形成單詞或字符串的多個字符,例如"Hello"或"Hello World"。
cout << 'a string'; // 錯誤
cout << "a string"; // 正確
  1. 使用分號標記語句的結尾。如果忘記使用分號,編譯器會認為語句在繼續。結果通常是編譯錯誤。
cout << "a string" // 錯誤
cout << 'a string'; // 錯誤
cout << "a string"; // 正確

修復其中錯誤的代碼

#include (iostream);
using namespace std;
int main()
{
  cout >> 'Hello World'
}
  • 第一個錯誤:括號代替了尖括號
hello.cpp:1:10: error: #include expects "FILENAME" or <FILENAME>
    1 | #include (iostream);
#include <iostream>;
  • 第二個錯誤:額外的分號
hello.cpp:1:20: warning: extra tokens at end of #include directive
    1 | #include <iostream>;

文件名/庫iostream的末尾添加了分號;不能在#include指令后添加分號,僅在語句末尾使用分號

  • 第三個錯誤:字符串字面量的引號類型錯誤
hello.cpp:5:11: warning: character constant too long for its type
    5 |   cout >> 'Hello World'

代碼使用單引號而不是雙引號。僅對單個字符使用單引號。應對字符串字面量(字符數組)使用雙引號。

  • 第四個錯誤:流運算符錯誤
hello.cpp: In function ‘int main()’:
hello.cpp:5:8: error: no match for ‘operator>>’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘const char [12]’)
    5 |   cout >> "Hello World"

cout對象使用<<。對cin對象使用>>

  • 第五個錯誤:缺少分號
hello.cpp: In function ‘int main()’:
hello.cpp:5:24: error: expected ‘;’ before ‘}’ token
    5 |   cout << "Hello World"

語句末尾需要加分號。

#include <iostream>
using namespace std;
int main()
{
  cout << "Hello World";
}
  • 為什么沒有返回不報錯

代碼末尾不包含return 0,但未引發任何錯誤。原因是,運行時假定將隱式返回類型作為main的整數。返回類型主要用於退出狀態。在這里,返回0或不返回任何內容都會使運行時假定代碼已成功退出

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM