# C 语法学习指南从 C 语言过渡--- **适用对象** 已熟练掌握 C 语言需快速学习 C 面向对象编程 **推荐阅读方式** 从上到下依次阅读每个知识点附带 C 语言对比---## 目录1. [C 与 C 的基础差异](#一c-与-c-的基础差异)2. [输入输出流 (iostream)](#二输入输出流-iostream)3. [命名空间 (namespace)](#三命名空间-namespace)4. [引用 (Reference)](#四引用-reference)5. [动态内存分配 (new / delete)](#五动态内存分配-new--delete)6. [类与对象 (Class Object)](#六类与对象-class--object)7. [构造函数 (Constructor)](#七构造函数-constructor)8. [析构函数 (Destructor)](#八析构函数-destructor)9. [this 指针](#九this-指针)10. [const 成员函数](#十const-成员函数)11. [成员初始化列表](#十一成员初始化列表)12. [类的组合](#十二类的组合)13. [string 类与字符数组](#十三string-类与字符数组)14. [C 常用头文件速查](#十四c-常用头文件速查)---## 一、C 与 C 的基础差异### 1.1 文件扩展名| 语言 | 扩展名 ||------|--------|| C | .c || C | .cpp、.cc、.cxx |### 1.2 头文件| C 语言 | C 等价写法 ||--------|-------------|| #include stdio.h | #include cstdio || #include string.h | #include cstring || #include math.h | #include cmath || #include stdlib.h | #include cstdlib |cpp// C 推荐写法名字前加 c去掉 .h#include cstdio // 对应 C 的 stdio.h#include cstring // 对应 C 的 string.h#include cmath // 对应 C 的 math.h### 1.3 bool 类型C 语言没有内置的 bool 类型需 #include stdbool.hC 内置cppbool flag true; // C 内置布尔类型bool isOK false;if (flag) {// 直接使用}---## 二、输入输出流 (iostream)### 2.1 基本用法这是 C 与 C 最明显的区别用 cout/cin 替代 printf/scanf。cpp#include iostreamusing namespace std;int main() {int a;double b;char c;// 输入cin 变量cin a; // 读取整数cin b; // 读取浮点数cin c; // 读取字符// 输出cout 内容cout Hello; // 输出字符串cout a; // 输出变量cout a a endl; // 链式输出// endl 相当于换行符 \n并刷新缓冲区return 0;}### 2.2 与 C 语言对比| C 语言 | C ||--------|-----|| printf(%d, x); | cout x; || scanf(%d, x); | cin x; || printf(\n); | cout endl; 或 cout \n; || 需要格式说明符 %d %f %s | 自动类型识别无需格式符 |### 2.3 读取包含空格的字符串cpp#include iostreamusing namespace std;int main() {char name[21];// 错误cin 遇到空格就停止// cin name; // 输入 zhang san 只能读到 zhang// 正确使用 cin.getline()cin.getline(name, 21); // 读取整行含空格最多20个字符cout name;return 0;}### 2.4 cin 与 cin.getline() 混用问题重要cppint main() {int id;char name[21];cin id; // 输入 1002缓冲区留下换行符 \ncin.ignore(); // 吸收掉换行符否则 getline 会读到空行cin.getline(name, 21); // 正常读取 zhang sancout ID: id endl;cout Name: name endl;return 0;}**原理** cin 读取后输入缓冲区会残留一个换行符 \n。cin.getline() 遇到换行符就立即结束会读到空字符串。所以需要用 cin.ignore() 把换行符吃掉。---## 三、命名空间 (namespace)### 3.1 概念命名空间是为了避免**命名冲突**。比如不同库中可能有同名的函数用命名空间来区分。cpp#include iostream// 不使用命名空间int main() {std::cout Hello std::endl; // 每次都要写 std::return 0;}// 使用命名空间using namespace std;int main() {cout Hello endl; // 可以省略 std::return 0;}### 3.2 三种用法cpp// 方式一全局引入最简单但可能污染命名空间using namespace std;// 方式二引入特定名称using std::cout;using std::endl;// 方式三每次使用时加前缀最安全std::cout Hello std::endl;---## 四、引用 (Reference)### 4.1 概念引用是变量的**别名**操作引用就是操作原变量。这是 C 新增的特性C 语言中没有。cppint a 10;int ref a; // ref 是 a 的引用别名ref 20; // 修改 ref 就是修改 acout a; // 输出 20### 4.2 与指针的对比| 特性 | 指针 | 引用 ||------|------|------|| 声明 | int *p a; | int ref a; || 使用 | *p 20; | ref 20;直接使用 || 可空 | 可以为 NULL | 必须初始化不能为空 || 可修改指向 | 可以指向别的变量 | 绑定后不能改变 || 取地址 | p 本身是地址 | ref 取地址 |cppvoid swap(int x, int y) { // 引用参数直接修改原变量int temp x;x y;y temp;}int main() {int a 1, b 2;swap(a, b); // 调用后 a2, b1无需传指针return 0;}### 4.3 常引用 (const reference)cppvoid print(const Point p) { // 不会修改 p且避免拷贝cout p.GetX();}---## 五、动态内存分配 (new / delete)### 5.1 基本用法C 用 new/delete 替代 C 的 malloc/free。| C 语言 | C ||--------|-----|| int *p malloc(sizeof(int)); | int *p new int; || *p 5; | int *p new int(5); || free(p); | delete p; || int *arr malloc(10 * sizeof(int)); | int *arr new int[10]; || free(arr); | delete[] arr; |cpp// 分配单个变量并初始化int *p new int(5); // 分配一个 int值为 5cout *p; // 输出 5delete p; // 释放内存// 分配数组int *arr new int[10]; // 分配 10 个 int 的数组delete[] arr; // 释放数组注意方括号### 5.2 关键区别| | malloc/free | new/delete ||------|-------------|------------|| 本质 | 函数 | 运算符 || 构造函数 | 不调用 | **自动调用构造函数** || 析构函数 | 不调用 | **自动调用析构函数** || 类型安全 | 需强转 (int*) | 自动返回正确类型指针 |---## 六、类与对象 (Class Object)### 6.1 基本概念类是 C 面向对象编程的核心。可以把类理解为 C 语言中 struct 的升级版。| 概念 | 类比 C 语言 ||------|------------|| 类 (Class) | struct 的增强版包含数据 函数 || 对象 (Object) | 结构体变量 || 成员变量 | 结构体字段 || 成员函数 | 操作该结构体的函数 |### 6.2 类的定义cppclass Student {public: // 公有成员外部可访问// 成员函数声明void Set(int id, char name[], char sex, int age);void Output();private: // 私有成员只能在类内部访问// 成员变量int ID;char name[21];char sex;int age;};### 6.3 访问权限| 关键字 | 访问范围 | 默认class | 默认struct ||--------|----------|--------------|----------------|| public | 任何地方都能访问 | - | struct 默认 || private | 只有类内部能访问 | class 默认 | - || protected | 类内部和子类能访问 | - | - |cppclass A {int a; // 默认 private};struct B {int b; // 默认 public};### 6.4 成员函数的类外定义cppclass Point {public:void Set(double xx, double yy); // 类内声明double GetX() { return x; } // 类内直接定义内联private:double x, y;};// 类外定义需要 类名:: 前缀void Point::Set(double xx, double yy) {x xx;y yy;}**语法格式** 返回类型 类名::函数名(参数列表) { 函数体 }### 6.5 创建和使用对象cppint main() {Student s; // 创建对象类似 C 的 struct Student s;s.Set(1001, 张三, M, 20); // 调用成员函数用 . 运算符s.Output();// 动态创建对象Student *ps new Student;ps-Set(1002, 李四, F, 19); // 指针用 - 运算符ps-Output();delete ps;return 0;}---## 七、构造函数 (Constructor)### 7.1 概念构造函数是**创建对象时自动调用**的特殊函数用于初始化对象。C 语言中需要手动写 init_xxx() 函数C 自动完成。### 7.2 特点| 特点 | 说明 ||------|------|| 函数名 | 必须与**类名完全相同** || 返回值 | **没有返回值**不写 void || 调用时机 | 创建对象时**自动调用** || 重载 | **可以重载**多个构造函数参数不同 |### 7.3 默认构造函数cppclass Point {public:Point() { // 无参构造函数默认构造函数x 0;y 0;}private:double x, y;};**重要规则** 如果类中定义了**任何一个构造函数**编译器就不再自动生成默认构造函数。cppclass Point {public:Point(double xx, double yy) { x xx; y yy; } // 定义了有参构造函数// 编译器不再生成默认构造函数 Point()private:double x, y;};Point p1; // 错误没有默认构造函数Point p2(1, 2); // 正确### 7.4 带默认参数的构造函数cppclass Point {public:// 一个构造函数通过默认参数实现无参和有参两种效果Point(double xx 0, double yy 0) : x(xx), y(yy) {}private:double x, y;};Point p1; // 调用 Point(0, 0)Point p2(1, 2); // 调用 Point(1, 2)Point p3(5); // 调用 Point(5, 0)只传一个参数### 7.5 构造函数重载cppclass Fraction {public:Fraction() : num(0), den(1) {} // 无参分子0分母1Fraction(int n) : num(n), den(1) {} // 单参分子n分母1Fraction(int n, int d) { // 双参分子n分母dif (d 0) d 1;num n;den d;}private:int num, den;};Fraction f1; // 调用 Fraction()Fraction f2(2); // 调用 Fraction(int)Fraction f3(-3, 4); // 调用 Fraction(int, int)---## 八、析构函数 (Destructor)### 8.1 概念析构函数是**对象销毁时自动调用**的特殊函数用于释放资源。### 8.2 特点| 特点 | 说明 ||------|------|| 函数名 | ~类名类名前加波浪号 || 返回值 | 没有返回值 || 参数 | 没有参数不能重载 || 数量 | 每个类只有一个 || 调用时机 | 对象生命周期结束时自动调用 |### 8.3 示例cppclass MyClass {public:MyClass() {data new int[100]; // 构造函数分配资源}~MyClass() {delete[] data; // 析构函数释放资源}private:int *data;};---## 九、this 指针### 9.1 概念每个对象都有一个隐含的 this 指针指向**对象自身**。cppclass Point {public:void Set(double x, double y) {this-x x; // this-x 是成员变量this-y y; // 右边的 x, y 是参数}private:double x, y;};---## 十、const 成员函数### 10.1 概念在函数声明后加 const表示该函数**不会修改对象**的任何成员变量。cppclass Point {public:double GetX() const { return x; } // const 成员函数double GetY() const { return y; }void Output() const { // 输出不修改对象cout ( x , y ) endl;}void Set(double xx, double yy) { // 修改对象不能加 constx xx;y yy;}private:double x, y;};### 10.2 规则- const 成员函数内部不能修改成员变量- const 成员函数只能调用其他 const 成员函数- const 对象只能调用 const 成员函数---## 十一、成员初始化列表### 11.1 概念在构造函数体执行之前用初始化列表直接初始化成员变量。cpp// 方式一构造函数体内赋值先默认初始化再赋值Point::Point(double xx, double yy) {x xx; // 赋值不是初始化y yy;}// 方式二初始化列表直接初始化更高效Point::Point(double xx, double yy) : x(xx), y(yy) {// 构造函数体可以为空或做额外操作}### 11.2 初始化顺序成员初始化的顺序**取决于类中声明的顺序**与初始化列表中的书写顺序无关。cppclass Test {int x, y, z; // 声明顺序x → y → zpublic:Test() : z(1), y(2), x(3) {} // 实际初始化顺序仍是 x → y → z};---## 十二、类的组合### 12.1 概念一个类可以包含另一个类的对象作为数据成员。cppclass Point {public:Point(double xx 0, double yy 0) : x(xx), y(yy) {}double GetX() const { return x; }double GetY() const { return y; }private:double x, y;};class Rectangle {public:Rectangle(Point p1, Point p2) : ltp(p1), rbp(p2) {}double GetLength() const { return rbp.GetX() - ltp.GetX(); }double GetWidth() const { return rbp.GetY() - ltp.GetY(); }double GetArea() const { return GetLength() * GetWidth(); }private:Point ltp; // 左上角点Point 对象Point rbp; // 右下角点Point 对象};---## 十三、string 类与字符数组### 13.1 C 风格字符串字符数组沿用 C 语言的写法使用 cstring 头文件。cpp#include cstringchar name[21];char src[] Hello;strcpy(name, src); // 复制字符串int len strlen(name); // 获取长度int cmp strcmp(name, Hello); // 比较字符串### 13.2 C string 类C 提供了更安全、更方便的 string 类。cpp#include stringusing namespace std;string name;string greeting Hello;name zhang san; // 直接赋值无需 strcpyname greeting World; // 字符串拼接用 号int len name.length(); // 获取长度bool eq (name test); // 直接比较用 ### 13.3 对比| 操作 | C 风格 (char[]) | C string ||------|----------------|------------|| 赋值 | strcpy(a, b); | a b; || 拼接 | strcat(a, b); | a a b; || 比较 | strcmp(a, b) 0 | a b || 长度 | strlen(a) | a.length() || 头文件 | cstring | string |---## 十四、C 常用头文件速查| 头文件 | 用途 ||--------|------|| iostream | 输入输出流cin, cout, endl || cstring | C 风格字符串函数strcpy, strlen || string | C string 类 || cmath | 数学函数sqrt, pow, abs, sin, cos || cstdlib | 通用工具NULL, atoi, rand, srand || cstdio | C 标准 I/Oprintf, scanf, FILE |---