汇总表:
| 特性 | C语言 | C++ |
|---|---|---|
| 编程范式 | 过程式编程 | 多范式(过程式、面向对象、泛型) |
| 头文件 | #include <stdio.h> |
#include <iostream> |
| 输入输出 | printf/scanf,需格式符 |
cin/cout,流操作,类型安全 |
| 函数重载 | 不支持 | 支持 |
| 变量声明 | 作用域开头(C89前) | 任意位置(使用前即可) |
| 内存管理 | malloc/free |
new/delete,自动调用构造/析构 |
| 引用类型 | 不支持 | 支持,变量别名 |
| 结构体 | 仅数据成员 | 可包含成员函数,类似class |
| 类与对象 | 不支持 | 支持,核心特性 |
| 常量定义 | const为只读变量 |
const可为真正常量 |
| 布尔类型 | 无内置(C99前) | 内置bool类型 |
💻 编程范式
-
C语言(过程式):程序围绕函数构建,数据和对数据的操作是分离的。
c#include <stdio.h> // 数据(结构体)和操作(函数)分离 struct Point { int x; int y; }; // 操作数据的函数 void printPoint(struct Point p) { printf("Point: (%d, %d)\n", p.x, p.y); } int main() { struct Point p1 = {1, 2}; printPoint(p1); // 调用函数处理数据 return 0; } -
C++(多范式,以面向对象为例):程序围绕对象构建,对象将数据(成员变量)和操作(成员函数)封装在一起。
c#include <iostream> using namespace std; // 类将数据和对数据的操作封装在一起 class Point { private: // 数据成员通常设为私有,实现封装 int x; int y; public: Point(int a, int b) : x(a), y(b) {} // 构造函数 void print() { // 成员函数,操作自身数据 cout << "Point: (" << x << ", " << y << ")" << endl; } }; int main() { Point p1(1, 2); // 创建对象 p1.print(); // 对象调用自己的方法 return 0; }
📁 头文件与命名空间
-
C语言 :头文件带
.h后缀,没有命名空间。c#include <stdio.h> // C标准头文件 #include <math.h> int main() { double root = sqrt(2.0); // 直接使用函数 printf("%f\n", root); return 0; } -
C++ :标准头文件通常无
.h后缀,使用std命名空间。c#include <iostream> // C++标准头文件 #include <cmath> // C++版本的C数学库,如cstdio, cstdlib int main() { // 使用`std::`前缀,或使用`using namespace std;` std::cout << std::sqrt(2.0) << std::endl; return 0; }
⌨️ 输入输出处理
-
C语言 :使用
printf和scanf,需格式控制符。c#include <stdio.h> int main() { int a; double d; printf("请输入一个整数和一个浮点数: "); scanf("%d %lf", &a, &d); // 需格式符和取址符& printf("a=%d, d=%.2f\n", a, d); // 需格式符 return 0; } -
C++ :使用
cin和cout流,类型自动识别。c#include <iostream> using namespace std; int main() { int a; double d; cout << "请输入一个整数和一个浮点数: "; cin >> a >> d; // 无需格式符,自动识别类型 cout << "a=" << a << ", d=" << d << endl; // 无需格式符 return 0; }
🔧 函数特性:重载与默认参数
-
C语言:不支持函数重载,不支持默认参数。
c#include <stdio.h> // 以下两个函数不能同时存在,编译错误 // int add(int a, int b) { return a + b; } // double add(double a, double b) { return a + b; } // 需用不同函数名 int add_int(int a, int b) { return a + b; } double add_double(double a, double b) { return a + b; } int main() { printf("%d\n", add_int(1, 2)); printf("%.2f\n", add_double(1.5, 2.5)); return 0; } -
C++:支持函数重载和默认参数。
c#include <iostream> using namespace std; // 函数重载:根据参数列表区分 int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; } // 默认参数 void greet(string name = "Guest") { cout << "Hello, " << name << "!" << endl; } int main() { cout << add(1, 2) << endl; // 调用int add cout << add(1.5, 2.5) << endl; // 调用double add greet("Alice"); // 输出: Hello, Alice! greet(); // 输出: Hello, Guest! 使用默认参数 return 0; }
💾 内存管理
-
C语言 :使用
malloc和free,需手动计算大小和类型转换。c#include <stdio.h> #include <stdlib.h> int main() { int *arr = (int*)malloc(5 * sizeof(int)); // 需计算大小和强制转换 if (arr == NULL) { // 错误处理 return -1; } for (int i = 0; i < 5; i++) { arr[i] = i; } free(arr); // 释放内存 return 0; } -
C++ :使用
new和delete,自动计算大小、类型安全,并调用构造/析构函数。c#include <iostream> using namespace std; int main() { int *arr = new int[5]; // 自动计算大小,无需转换 for (int i = 0; i < 5; i++) { arr[i] = i; } delete[] arr; // 释放数组内存 // 对于对象,new/delete会调用构造和析构函数 // MyClass *obj = new MyClass(); // delete obj; return 0; }
🔗 引用类型
-
C语言:只有指针,没有引用。
c#include <stdio.h> void swap(int *a, int *b) { // 使用指针 int temp = *a; *a = *b; *b = temp; } int main() { int x = 10, y = 20; swap(&x, &y); // 传递地址 printf("x=%d, y=%d\n", x, y); return 0; } -
C++:支持引用,作为变量的别名,更安全易用。
c#include <iostream> using namespace std; void swap(int &a, int &b) { // 使用引用 int temp = a; a = b; b = temp; } int main() { int x = 10, y = 20; int &ref = x; // ref是x的引用(别名) ref = 100; // 修改ref等同于修改x cout << "x=" << x << endl; // 输出100 swap(x, y); // 传递变量本身,语法更简洁 cout << "x=" << x << ", y=" << y << endl; return 0; }
🧱 结构体与类
-
C语言结构体:仅包含数据成员。
c#include <stdio.h> struct Point { int x; int y; }; // 操作Point的函数需单独存在 void printPoint(struct Point p) { printf("(%d, %d)\n", p.x, p.y); } int main() { struct Point p1 = {10, 20}; printPoint(p1); return 0; } -
C++结构体/类 :可包含数据成员和成员函数。
struct默认公有继承,class默认私有继承。c#include <iostream> using namespace std; struct Point { // 在C++中,struct可包含函数 int x; int y; void print() { // 成员函数 cout << "(" << x << ", " << y << ")" << endl; } }; class Rectangle { // class默认成员为private int width, height; public: Rectangle(int w, int h) : width(w), height(h) {} int area() { return width * height; } }; int main() { Point p1 = {10, 20}; p1.print(); // 结构体对象调用自己的方法 Rectangle rect(3, 4); cout << rect.area() << endl; return 0; }
⚙️ 变量声明位置
-
C89前:变量必须在作用域开头声明。
cvoid func() { int a = 10; // 必须在开头 // ... 其他代码 int b = 20; // C89前错误 } -
C++:变量可在使用前的任意位置声明。
cvoid func() { for (int i = 0; i < 10; i++) { // i在for循环内声明 // ... } int b = 20; // 随时声明 }
⚙️ const常量
-
C语言 :
const变量可视为"只读变量",不能用作数组大小(除非VLA)。cconst int size = 10; // int arr[size]; // 在C中可能报错(除非C99的VLA) -
C++ :
const变量是真正的编译期常量,可定义数组大小。cconst int size = 10; int arr[size]; // C++中合法
⚙️ 布尔类型
-
C语言 :无内置
bool(C99前需用int,C99后需#include <stdbool.h>)。c#include <stdbool.h> // C99后 int isReady = 0; // 传统C用法,0假,非0真 bool flag = true; // C99后 -
C++ :内置
bool类型。cbool isReady = false; bool isDone = true;
⚙️ 异常处理
-
C语言 :通过返回值或
setjmp/longjmp处理错误。c#include <stdio.h> #include <setjmp.h> jmp_buf env; int riskyFunc() { if (error) { longjmp(env, 1); // 跳转 } return 0; } -
C++ :支持
try/catch/throw。c#include <iostream> using namespace std; int main() { try { if (error) throw runtime_error("An error occurred"); } catch (const exception& e) { cerr << e.what() << endl; } return 0; }
💡 如何选择C语言或C++
- 选择C语言 :当项目对性能和控制力有极致追求 ,或者运行在资源极度受限的环境中时,C语言是更优选择。例如开发操作系统内核、嵌入式系统固件、硬件驱动等。
- 选择C++ :当需要构建大型、复杂的应用程序 ,并且对代码的可维护性、可扩展性要求较高时,C++的优势更为明显。例如游戏引擎、图形界面程序、高频交易系统、大型基础软件库等。C++的面向对象特性和丰富的标准库能有效支持大规模软件开发。