【c++面向对象编程】第1篇:从C到C++:面向对象编程思想入门

目录

一、一个真实的故事

二、C语言的过程式思维:数据是数据,操作是操作

三、C++的面向对象思维:把数据和操作绑在一起

四、三个核心概念:用一个例子串起来

[1. 封装:把东西包起来](#1. 封装:把东西包起来)

[2. 继承:复用已有的东西](#2. 继承:复用已有的东西)

[3. 多态:同一个动作,不同表现](#3. 多态:同一个动作,不同表现)

五、一个小对比:到底好在哪里?

六、初学者最常陷入的误区

七、这一篇的收获


一、一个真实的故事

去年我刚转C++的时候,写了一个学生管理系统。

用C的思路,我定义了一个结构体,然后写了一堆函数:add_student()find_student()print_score()......代码跑得挺好,直到有一天,产品经理说:"每个学生需要加一个'手机号'字段。"

我改了结构体,然后满屏找哪些函数用到了学生数据------有6个文件,20多处调用。改完编译,一堆报错,折腾了一下午。

后来我用C++的类重写了一遍,同样的需求,半小时搞定。

这不是技术高低的问题,是组织代码的方式变了。


二、C语言的过程式思维:数据是数据,操作是操作

C语言编程的核心思路是:你有一堆数据,然后写一堆函数去处理它们

c

复制代码
// C语言风格
struct Student {
    char name[20];
    int score;
};

void printStudent(struct Student* s) {
    printf("%s: %d\n", s->name, s->score);
}

int main() {
    struct Student s = {"张三", 85};
    printStudent(&s);
    return 0;
}

数据(Student结构体)和操作(printStudent函数)是分开的。代码少的时候很清晰,但项目一大,问题就来了:

  • 哪个函数改了哪个数据?很难追踪

  • 新增一个字段,所有相关函数都要检查

  • 多个模块都用同一个结构体,改一处可能炸一片

这就是过程式的痛点:数据和操作是松散的,维护成本随代码量线性增长


三、C++的面向对象思维:把数据和操作绑在一起

面向对象告诉你:一个物体的数据和能对它做的事情,应该放在一起

cpp

复制代码
// C++风格
class Student {
private:
    char name[20];
    int score;
public:
    void setName(const char* n) { strcpy(name, n); }
    void setScore(int s) { score = s; }
    void print() const {
        cout << name << ": " << score << endl;
    }
};

int main() {
    Student s;
    s.setName("张三");
    s.setScore(85);
    s.print();
    return 0;
}

看起来只是语法变了,但本质不一样:Student这个"类"现在是一个完整的整体,数据藏在里面,外部只能通过public函数去操作。

这就是封装------把数据和操作它的函数包在一起,把内部细节藏起来。


四、三个核心概念:用一个例子串起来

光说概念不好懂,我用一个"动物"的例子把封装、继承、多态串一遍。

1. 封装:把东西包起来

cpp

复制代码
class Animal {
private:
    int age;        // 外部不能直接访问
public:
    void setAge(int a) { 
        if (a > 0) age = a;  // 可以加校验逻辑
    }
    int getAge() const { return age; }
    void speak() { cout << "动物叫" << endl; }
};

外部的人只能通过setAge()来改年龄,不能直接animal.age = -5封装保护了数据的一致性

2. 继承:复用已有的东西

cpp

复制代码
class Dog : public Animal {  // Dog 继承 Animal
public:
    void wagTail() { cout << "摇尾巴" << endl; }
};

Dog自动拥有了Animal的所有成员(age、setAge、getAge、speak),还可以加自己的wagTail不需要重新写一遍

这就是继承的意义:站在别人的肩膀上。

3. 多态:同一个动作,不同表现

cpp

复制代码
class Cat : public Animal {
public:
    void speak() { cout << "喵喵喵" << endl; }  // 重写
};

void letItSpeak(Animal* a) {
    a->speak();  // 传Dog就汪汪,传Cat就喵喵
}

同样的speak()调用,传入不同对象,表现不一样。代码写的是一套逻辑,跑出来是多种效果


五、一个小对比:到底好在哪里?

用C写一个"图形面积计算",你可能这样:

c

复制代码
// C:需要手动判断类型
struct Circle { float r; };
struct Rect { float w, h; };
float area(void* shape, int type) {
    if (type == 1) return ((Circle*)shape)->r * 3.14;
    if (type == 2) return ((Rect*)shape)->w * ((Rect*)shape)->h;
}
// 每加一个新形状,修改这个函数 —— 风险大

用C++写:

cpp

复制代码
class Shape {
public:
    virtual float area() = 0;  // 纯虚函数
};
class Circle : public Shape {
    float r;
public:
    float area() override { return r * r * 3.14; }
};
class Rect : public Shape {
    float w, h;
public:
    float area() override { return w * h; }
};
// 加新形状:加一个新类,已有代码完全不用改

C++的版本更安全、更容易扩展。这就是OOP对大型项目友好的原因。


六、初学者最常陷入的误区

刚学的时候我也犯过这些错,提前给你打预防针:

  1. 把所有东西都塞进一个类

    不是所有代码都需要是类。工具函数用命名空间就行,别硬塞。

  2. 滥用getter/setter,把私有变量全暴露出去

    如果每个私有变量都配一对get/set,那封装等于没做。想想"为什么外部要改它"。

  3. 以为"面向对象=用class"

    用了class不等于用了OOP思想。OOP核心是职责划分、依赖管理、可维护性,不是语法。


七、这一篇的收获

读完这篇,你应该记住三句话:

  • 封装:数据和操作放一起,内部细节藏起来

  • 继承:用已有类派生出新类,复用代码

  • 多态:同一个接口,不同对象有不同实现

下一篇我们会真正动手写第一个完整的类,从构造函数到析构函数,把对象的生命周期搞明白。

💡 一个小作业:找一个你以前用C写过的程序(比如通讯录、图书管理),想一想------如果变成类,你会怎么拆分?


下一篇预告:第2篇《类与对象(一):定义第一个类------成员变量与成员函数》,我们将真正写代码,从0构建一个可用的类。

相关推荐
Master_oid1 小时前
机器学习41:利用KNN算法实现手写数字识别
深度学习·算法·机器学习
liuhuizuikeai1 小时前
菜品抽奖活动MFC+服务端
c++·windows·mfc
ouliten1 小时前
C++笔记:Lambda表达式
c++·笔记
OYangxf1 小时前
力扣hot100【子串专题】
算法·leetcode·职场和发展
minji...1 小时前
Linux 网络基础(五)守护进程化,前后台进程组,作业,会话,setsid(),daemon(),端口号频繁更换问题
linux·运维·服务器·网络·c++·tcp/ip
WL_Aurora1 小时前
Python 算法基础篇之元组与列表
python·算法
Brilliantwxx1 小时前
【算法题】递归树+哈希表+分治异或+双指针
开发语言·c++·笔记·算法
yugi9878381 小时前
经典三维表面重建算法(C语言实现)
c语言·开发语言·算法
Hello:CodeWorld1 小时前
高性能多线程数据采集与持久化方案设计与实现
开发语言·c++