一、C++与面向对象概述
大家好,我是你们这门课的老师。今天咱们聊聊C++的起源,以及它和C语言那点事儿。说实话,我刚开始学编程那会儿,也觉得这些历史背景挺枯燥的。但后来在实际项目中踩过几次坑,才明白——不了解语言的来龙去脉,写代码就容易「知其然不知其所以然」。
1.1 C++语言发展史
C++诞生于上世纪80年代初。它的父亲叫Bjarne Stroustrup,当时在贝尔实验室工作。他原本是想给C语言加点「面向对象」的料,结果一不小心搞出了个新语言。
我简单梳理一下关键节点:
| 年份 | 事件 |
|---|---|
| 1979年 | Bjarne开始研究「带类的C」 |
| 1983年 | 正式命名为C++(++是C的自增运算符) |
| 1998年 | 第一个国际标准C++98发布 |
| 2011年 | C++11发布,现代C++的起点 |
| 2014/2017/2020 | 后续标准持续更新 |
为什么叫C++?说白了,就是「C语言的升级版」。++运算符在C里表示自增1,所以C++这个名字,意思就是「比C更进一步」。
1.2 C++与C语言的关系
这个问题我经常被问到:「老师,我学过C,学C++是不是很容易?」
嗯,对,也不全对。
C++几乎兼容C语言的所有语法。你写的C代码,大部分可以直接拿到C++编译器里跑。但反过来不行——C++多了很多C没有的东西,比如类、继承、多态、异常处理等等。
我个人习惯把C++看作「C语言的超集 + 面向对象 + 泛型编程 + 标准库」。你想想看,C语言能做的事,C++都能做;但C++能做的事,C语言做起来就费劲了。
核心区别一句话:C是面向过程的,C++是面向对象的。C关注「怎么做」,C++关注「谁来做」。
1.3 面向对象编程的四大特性
面向对象编程(OOP)有四个核心特性。我当年面试的时候,面试官让我用一句话概括,我说:「封装、继承、多态、抽象,缺一不可。」
咱们一个一个来看。
封装
封装就是把数据和操作数据的方法打包在一起,对外只暴露接口,隐藏内部实现。我在项目中遇到过一个问题:有个同事把类的成员变量全写成public,结果到处都能改,最后查bug查了三天。嗯,这就是没做好封装的代价。
继承
继承允许你基于已有的类创建新类。子类可以复用父类的代码,也可以扩展自己的功能。说白了,就是「儿子继承老子的家产,还能自己再赚点」。
多态
多态的意思是「同一个接口,多种实现」。比如你定义一个「画图」函数,圆形类去画圆,方形类去画方。调用的时候不用管具体是什么形状,统一调用「画图」就行。我曾经用多态重构过一个项目,代码量直接砍掉40%。
抽象
抽象就是只关注「做什么」,不关注「怎么做」。比如你开车,只需要知道方向盘、油门、刹车怎么用,不需要知道发动机内部怎么工作的。抽象让我们能站在更高的层次思考问题。
我的建议:刚开始学的时候,别急着把四个特性全搞透。先理解封装和继承,再慢慢啃多态和抽象。一口吃不成胖子。
1.4 第一个C++程序:Hello World
好了,理论说够了,咱们来写点代码。第一个程序,永远是Hello World。
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
这段代码很简单,但我还是想拆开讲讲:
#include <iostream>:引入输入输出流库。没有它,你就没法用cout。using namespace std;:告诉编译器,我们用的是标准命名空间。后面会细说。int main():程序的入口函数。每个C++程序都必须有一个main函数。cout << "Hello, World!" << endl;:输出字符串到控制台。endl表示换行。return 0;:告诉操作系统,程序正常结束。
注意:C++是大小写敏感的。你把main写成Main,编译器会直接报错。我曾经有个学生,找了半小时bug,结果就是大小写写错了。
1.5 命名空间(namespace)的基本使用
命名空间是C++用来解决命名冲突的机制。你想想看,一个项目里几百个文件,万一两个文件里定义了同名的函数怎么办?命名空间就是给这些名字加个「姓氏」。
基本用法:
namespace MySpace {
int value = 42;
void show() {
cout << "Value: " << value << endl;
}
}
int main() {
MySpace::show(); // 通过 :: 访问命名空间中的成员
return 0;
}
这里::叫作用域解析运算符。它的作用就是告诉编译器:「我要找的是MySpace里的show,不是别的show。」
你也可以用using关键字偷个懒:
using namespace MySpace;
// 之后就可以直接写 show() 了
但我个人建议:在头文件里尽量不要用using namespace std;。为什么?因为头文件会被很多源文件包含,你这一using,相当于把整个std命名空间暴露给所有包含它的文件,很容易引发命名冲突。我在项目里吃过这个亏,后来就养成了「头文件里不用using」的习惯。
避坑指南:如果你只用到std里的cout,可以写成using std::cout;,这样只引入cout,不会把整个std都拉进来。更安全,也更清晰。
知识体系总览
下面这张图,是我自己画的本章知识结构。你可以把它当作一张「地图」,学完本章后对照着检查自己有没有遗漏。
好了,第一章的内容就到这儿。记住,C++不是一门「学完就能写所有东西」的语言,但它是一门「学好了就能写出高质量代码」的语言。咱们慢慢来,不着急。
公众号:蓝海资料掘金营,微信deep3321