Skip to content

Ch 4: 第一个 C++ 程序详解

  • 理解 C++ 程序的基本结构
  • 掌握 main() 函数的规范
  • 理解 #include 和预处理器
  • 熟悉编译和运行流程
  • 理解命名空间的概念

Python 版本:

hello.py
print("Hello, World!")

C++ 版本:

hello.cpp
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
// 第 1 行:注释
// 注释不会被编译,用于人类阅读
// C++ 有两种注释:
// - 单行注释:// 到行尾
// - 多行注释:/* ... */
// 第 2 行:预处理器指令
#include <iostream>
// #include 告诉编译器"包含" iostream 文件的内容
// iostream 包含 std::cout、std::cin 等输入输出功能
// 类似 Python 的 import,但工作方式不同
// 第 4 行:主函数 - 程序入口
int main() {
// int = 返回类型(整数)
// main = 函数名(特殊:程序入口)
// () = 空参数列表
// 第 5 行:输出语句
std::cout << "Hello, World!" << std::endl;
// std::cout = 标准输出流(屏幕)
// << = 流插入运算符(把数据"插入"到流中)
// "..." = 字符串字面量
// std::endl = 换行 + 刷新缓冲区
// ; = 语句结束符(C++ 每条语句以分号结尾)
// 第 6 行:返回
return 0;
// 0 = 返回值给操作系统
// 0 表示"程序正常结束"
// 非 0 表示"出错"
}

main() 是每个 C++ 程序的入口点,操作系统通过调用 main() 来运行你的程序。

// 1. 最简形式(不接受参数)
int main() {
return 0;
}
// 2. 带命令行参数(类似 sys.argv)
int main(int argc, char* argv[]) {
// argc = 参数个数
// argv = 参数数组
// argv[0] = 程序名
// argv[1] = 第一个参数
// ...
return 0;
}
// 3. 使用 std::vector 风格的 argv(C++20)
int main(int argc, char* argv[]) {
for (int i = 0; i < argc; ++i) {
std::cout << "argv[" << i << "]: " << argv[i] << std::endl;
}
return 0;
}
args.cpp
#include <iostream>
#include <string>
int main(int argc, char* argv[]) {
std::cout << "程序名: " << argv[0] << std::endl;
for (int i = 1; i < argc; ++i) {
std::cout << "参数 " << i << ": " << argv[i] << std::endl;
}
std::cout << "共 " << argc << " 个参数" << std::endl;
return 0;
}
Terminal window
# 编译运行
g++ -std=c++20 args.cpp -o args
./args hello world 42
# 输出:
# 程序名: ./args
# 参数 1: hello
# 参数 2: world
# 参数 3: 42
# 共 4 个参数
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
int main() {
// 两种成功退出方式(等价)
return 0;
// return EXIT_SUCCESS;
// 失败时返回非零值
// return 1;
// return EXIT_FAILURE;
}

Python 的 import 在运行时工作,C++ 的 #include 在编译前(预处理阶段)工作:

// 你写的代码:
#include <iostream>
int main() {
std::cout << "hello";
}
// 预处理器展开后(大概是这样):
// iostream 的全部内容被"复制粘贴"到这里
// 然后编译器处理展开后的代码
#include <iostream> // 系统头文件,编译器查找系统目录
#include "myheader.h" // 本项目头文件,查找当前目录和指定目录
#include "../include/utils.h" // 相对路径
#include "/full/path/to/header.h" // 绝对路径(不推荐)
// utils.h - 头文件
#ifndef UTILS_H // 头文件保护宏(防止重复包含)
#define UTILS_H
// 函数声明
int add(int a, int b);
double square(double x);
// 内联函数
inline int double_value(int x) {
return x * 2;
}
// 类声明
class Calculator {
public:
int add(int a, int b);
};
#endif // UTILS_H
// utils.cpp - 实现文件
#include "utils.h"
int add(int a, int b) {
return a + b;
}
double square(double x) {
return x * x;
}
int Calculator::add(int a, int b) {
return a + b;
}
// 定义常量
#define PI 3.14159
#define MAX_SIZE 100
// 条件编译
#ifdef DEBUG
std::cout << "Debug mode" << std::endl;
#else
std::cout << "Release mode" << std::endl;
#endif
// 现代 C++ 推荐用 const/constexpr 而不是 #define
constexpr double PI = 3.14159; // 类型安全,有作用域

命名空间是 C++ 组织代码的方式,防止名字冲突:

# Python - 模块避免冲突
import collections
import mycollections
collections.defaultdict() # 标准库
mycollections.defaultdict() # 你的代码
// C++ - 命名空间
namespace std {
// 标准库的所有东西都在 std 命名空间
class ostream;
class istream;
}
namespace myproject {
class vector { /* 不会和 std::vector 冲突 */ };
}
#include <iostream> // std::cout 在 iostream 中定义
int main() {
// 完全限定名
std::cout << "Hello" << std::endl;
// using 声明 - 引入单个名字
using std::cout;
using std::endl;
cout << "Hello" << endl;
// using 命名空间 - 引入整个命名空间(慎用!)
using namespace std; // 在大型项目中可能造成名字冲突
cout << "Hello" << endl;
return 0;
}
// C++17 嵌套命名空间语法
namespace myproject::utils::math {
int add(int a, int b) { return a + b; }
}
// 等价于
namespace myproject {
namespace utils {
namespace math {
int add(int a, int b) { return a + b; }
}
}
}
// 使用
int main() {
myproject::utils::math::add(1, 2);
}
#include <iostream>
int main() {
// 输出
std::cout << "Hello"; // 字符串
std::cout << 42; // 整数
std::cout << 3.14; // 浮点数
std::cout << 'A'; // 字符
std::cout << true; // 布尔值(输出 1)
// 连续输出
std::cout << "Value: " << 42 << std::endl;
// 输入
int age;
std::cin >> age; // 从键盘读取整数到 age
std::string name;
std::cin >> name; // 读取字符串(空格分隔)
// 连续读取
int x, y;
std::cin >> x >> y; // 读取两个整数
return 0;
}
// endl = 换行 + 刷新缓冲区
std::cout << "First line" << std::endl;
std::cout << "Second line" << std::endl;
// "\n" = 只是换行,不刷新
std::cout << "First line\n";
std::cout << "Second line\n";
// 什么时候用 endl?
// 当你需要立即看到输出时(如调试)
// 性能敏感时用 "\n",因为刷新缓冲区有开销
#include <iostream>
#include <iomanip> // 格式化控制
int main() {
// 整数进制
int n = 255;
std::cout << std::dec << n << std::endl; // 255
std::cout << std::hex << n << std::endl; // ff
std::cout << std::oct << n << std::endl; // 377
// 浮点数精度
double pi = 3.14159265;
std::cout << std::setprecision(4) << pi << std::endl; // 3.142
std::cout << std::fixed << std::setprecision(2) << pi << std::endl; // 3.14
// 宽度和对齐
std::cout << std::setw(10) << std::left << "hello" << std::endl;
std::cout << std::setw(10) << std::right << "world" << std::endl;
return 0;
}
// 单行注释 - // 到行尾
// 这是注释,不会被编译
/*
* 多行注释
* 可以跨行
*/
/**
* 文档注释
* 用于生成文档
* Doxygen 等工具会处理
*/
// C++ 没有 Python 的 """ 三引号注释
// 但可以用 /* */ 模拟
/* This is a multi-line
comment in C++ */
源代码 (hello.cpp)
│
▼ 1. 预处理 (Preprocessing)
预处理文件 (hello.ii/hello.i)
│
▼ 2. 编译 (Compilation)
汇编文件 (hello.s)
│
▼ 3. 汇编 (Assembly)
目标文件 (hello.o/hello.obj)
│
▼ 4. 链接 (Linking)
可执行文件 (hello/hello.exe)
Terminal window
# 1. 预处理
g++ -E hello.cpp -o hello.i
# 展开 #include, #define 等
# 2. 编译到汇编
g++ -S hello.i -o hello.s
# 生成汇编代码
# 3. 汇编到目标文件
g++ -c hello.cpp -o hello.o
# 生成机器码(未链接)
# 4. 链接
g++ hello.o -o hello
# 链接库函数,生成可执行文件
utils.h
int add(int a, int b);
// utils.cpp
#include "utils.h"
int add(int a, int b) {
return a + b;
}
// main.cpp
#include <iostream>
#include "utils.h"
int main() {
std::cout << add(1, 2) << std::endl;
return 0;
}
Terminal window
# 分别编译
g++ -c utils.cpp -o utils.o
g++ -c main.cpp -o main.o
# 链接
g++ main.o utils.o -o program
greet.cpp
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
int main() {
// 欢迎信息
std::cout << "====================================" << std::endl;
std::cout << " 个人信息收集程序" << std::endl;
std::cout << "====================================" << std::endl;
// 收集姓名
std::cout << "\n请输入你的姓名: ";
std::string name;
std::getline(std::cin, name); // 读取整行,包括空格
// 收集年龄
std::cout << "请输入你的年龄: ";
int age;
std::cin >> age;
// 收集城市
std::cout << "请输入你所在城市: ";
std::string city;
std::cin >> city;
// 显示收集的信息
std::cout << "\n------------------------------------" << std::endl;
std::cout << " 信息确认" << std::endl;
std::cout << "------------------------------------" << std::endl;
std::cout << std::left;
std::cout << std::setw(10) << "姓名:" << name << std::endl;
std::cout << std::setw(10) << "年龄:" << age << std::endl;
std::cout << std::setw(10) << "城市:" << city << std::endl;
// 简单判断
if (age >= 18) {
std::cout << "\n你是一个成年人。" << std::endl;
} else {
std::cout << "\n你是一个未成年人。" << std::endl;
}
std::cout << "感谢使用!" << std::endl;
return 0;
}

编译运行:

Terminal window
g++ -std=c++20 -o greet greet.cpp
./greet
# 输出:
# ====================================
# 个人信息收集程序
# ====================================
#
# 请输入你的姓名: Alice Wang
# 请输入你的年龄: 25
# 请输入你所在城市: Beijing
#
# ------------------------------------
# 信息确认
# ------------------------------------
# 姓名: Alice Wang
# 年龄: 25
# 城市: Beijing
#
# 你是一个成年人。
# 感谢使用!
  • C++ 程序从 main() 开始执行
  • #include 在预处理时展开内容
  • std::cout 和 << 用于输出
  • std::cin 和 >> 用于输入
  • 编译四步:预处理 → 编译 → 汇编 → 链接
  • return 0 表示程序正常结束
  • 命名空间 std:: 组织标准库代码

下章预告:ch05 学习 C++ 的变量声明、基本类型和类型系统。