详细介绍:初遇C++:一场始于“相似”却归于“惊艳”的编程之旅
相遇
2025年,当“C++ 40周年”的话题在技术圈刷屏时,我正握着大二《C++程序设计》的课本,在类与对象的迷宫里跌跌撞撞。作为一个刚从C语言“通关”的编程新手,这场与C++的相遇,起初充满了“似曾相识”的错觉,直到后来才惊觉,我推开的是一扇通往更广阔编程世界的大门。
第一次敲下C++代码时,我甚至有些“不屑”——include <iostream> 虽然和C的 include <stdio.h> 不一样,但int main()的入口、for循环的结构、if-else的逻辑,分明就是熟悉的配方。我得意地跟室友炫耀:“C++不就是C的‘加强版’吗?换了个名头而已。”那时的我还不知道,这份轻视很快就会被现实击碎。

转折点
转折点发生在学习“类与对象”的那节课。当老师用class定义出一个“学生”类,把姓名、学号、成绩这些“属性”和计算平均分、打印信息这些“行为”封装在一起时,我突然愣住了。比如这样一段代码:
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
// 私有属性:仅类内部可访问
string name;
int id;
double scores[3];
public:
// 构造函数:初始化对象
Student(string n, int i, double s1, double s2, double s3) {
name = n;
id = i;
scores[0] = s1;
scores[1] = s2;
scores[2] = s3;
}
// 成员函数:计算平均分
double getAverage() {
return (scores[0] + scores[1] + scores[2]) / 3;
}
// 成员函数:打印学生信息
void printInfo() {
cout << "学号:" << id << endl;
cout << "姓名:" << name << endl;
cout << "平均分:" << getAverage() << endl;
}
};
int main() {
Student stu("张三", 2024001, 85, 92, 78);
stu.printInfo();
return 0;
}
原来代码可以不是冷冰冰的指令堆砌,而是像搭积木一样,把现实世界的事物“复刻”到屏幕上。对比C语言里需要用结构体加函数指针才能勉强实现的功能,C++的封装就像给编程安上了“外挂”,让复杂的逻辑变得清晰又优雅。我第一次体会到,Bjarne Stroustrup在设计C++时,那句“让C语言程序员能无痛过渡,却能做更多事”的初心,藏着怎样的智慧。
但这份“惊艳”很快就伴随着“头疼”。当课程推进到多继承时,我对着屏幕上两个父类的同名函数抓耳挠腮,比如下面这种场景:
class A {
public:
void show() { cout << "This is class A" << endl; }
};
class B {
public:
void show() { cout << "This is class B" << endl; }
};
class C : public A, public B {
// 同时继承A和B的show()方法
};
int main() {
C c;
// c.show(); // 编译报错:二义性,无法确定调用哪个父类的show()
c.A::show(); // 需显式指定父类
return 0;
}
当模板和重载出现,看着两个一模一样名字的函数只因参数列表不同就能实现不同功能,我甚至怀疑自己是不是眼花了。比如函数重载的示例:
// 重载函数:参数类型不同
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int main() {
cout << add(2, 3) << endl; // 调用int版本,输出5
cout << add(2.5, 3.5) << endl; // 调用double版本,输出6.0
return 0;
}
有一次调试代码到深夜,明明逻辑没错却始终报错,最后发现是因为不小心调用了父类的隐藏函数。那天我对着屏幕苦笑,突然想起老师课堂上说的“C++有的功能,连发明人都搞不明白”——原来这句话不是调侃,是真的“诚不我欺”。我甚至幼稚地想,难道C++真的在随着开发者的使用“悄悄进化”?

不过,这些“痛苦”的时刻,反而让C++在我心里变得更鲜活。记得有一次小组作业要做一个简单的图书管理系统,我和队友为了“要不要用继承实现不同类型的图书”争得面红耳赤。他觉得用结构体更简单,我却坚持用类封装更符合“现实逻辑”。我当时写的类继承结构大概是这样:
// 基类:图书
class Book {
protected:
string title;
string author;
public:
Book(string t, string a) : title(t), author(a) {}
virtual void showInfo() { // 虚函数:实现多态
cout << "书名:" << title << endl;
cout << "作者:" << author << endl;
}
// 预留接口,方便后续扩展
virtual void addBorrowRecord(string user) {}
};
// 派生类:小说
class Novel : public Book {
private:
string genre;
public:
Novel(string t, string a, string g) : Book(t, a), genre(g) {}
void showInfo() override {
Book::showInfo();
cout << "类型:小说(" << genre << ")" << endl;
}
};
// 派生类:教材
class Textbook : public Book {
private:
string subject;
public:
Textbook(string t, string a, string s) : Book(t, a), subject(s) {}
void showInfo() override {
Book::showInfo();
cout << "科目:" << subject << endl;
}
};
最后我们各自写了版本,对比后发现,虽然我的代码行数更多,但后续添加“借阅记录”功能时,只需要在基类Book中实现addBorrowRecord方法,所有派生类都能继承使用,而他的结构体版本却要修改大量代码。那天傍晚,我们在食堂边吃边聊,从面向过程聊到面向对象,从C的“简洁高效”聊到C++的“灵活强大”,思维碰撞出的火花,比代码运行成功时的喜悦更让人难忘。
成长
现在的我,依然会为了模板的语法细节卡壳,依然会在调试多态代码时掉头发,但我对C++的感情早已从最初的“轻视”变成了“敬畏”。我渐渐明白,编程学的从来不是那些冰冷的语句和语法,而是解决问题的思路和灵感——就像C++既能用底层语法操作内存,又能用高级特性实现抽象,它教会我的,是根据不同的场景选择最合适的工具,是在“高效”与“优雅”之间找到平衡。
C++40岁生日快乐
今年是C++的40岁生日,它从1985年的第一个版本走到今天,支撑起了操作系统、游戏引擎、AI框架这些计算世界的基石。而我,一个刚接触它半年的大二学生,就像站在巨人肩膀上的孩子,正慢慢触摸着它庞大而精密的骨架。我或许还无法深刻理解它在技术史上的重量,但我知道,这场始于“相似”却归于“惊艳”的编程之旅,才刚刚开始。
#include <iostream>
#include <string>
using namespace std;
int main(){
cout << "C++, 40岁生日快乐";
return 0;
}
期许
如果有机会能和Bjarne Stroustrup先生面对面,我想问问他:当年在设计C++时,是否想到过这个语言会陪伴一代又一代开发者成长?是否知道,在遥远的中国校园里,有一个大二学生因为它,第一次感受到了编程世界的温度与深度?
40岁的C++,依然年轻;而我的编程之路,才刚刚启程。未来,我想带着这份对C++的热爱,继续在代码的世界里探索,期待有一天,能成为那个为这个“老朋友”添砖加瓦的人。

浙公网安备 33010602011771号