【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构建一个可用的类。

相关推荐
NiceCloud喜云20 小时前
Opus 4.8 的 Effort Control 怎么选:Low 到 Max 五档策略
android·java·大数据·前端·c++·python·spring
小羊在睡觉20 小时前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
cjhbachelor20 小时前
c++继承
c++
3DVisionary20 小时前
蓝光三维扫描:医疗制造的精度焦虑怎么解
人工智能·算法·制造·蓝光三维扫描·医疗制造·三维检测·义齿检测
好评笔记21 小时前
机器学习面试八股——常用损失函数
人工智能·深度学习·算法·机器学习·校招
weixin_4684668521 小时前
全局与局部注意力机制新手实战指南
人工智能·python·深度学习·算法·自然语言处理·transformer·注意力机制
肩上风骋21 小时前
C++14特性
开发语言·c++·c++14特性
_日拱一卒21 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
珂朵莉MM21 小时前
第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--束搜索
人工智能·算法
Omics Pro1 天前
首个!外源天然产物综合性代谢图谱
数据库·人工智能·算法·机器学习·r语言