面向对象!(C++ 版)
本文最后更新于 18 天前,其中的信息可能已经有所发展或是发生改变。

用实例来介绍面向对象

类(Class)

事物的“模板”

假设你是家具设计师,设计了一款“沙发”。在生产前,你需要创建一份设计图纸,这份图纸定义了沙发的结构(如尺寸、材质、颜色)和功能(如可坐、可躺、可收纳)。

代码中的类:

#include <iostream>
#include <string>
using namespace std;

class Sofa {
private: // 私有访问权限,隐藏内部属性
    string color;
    string material;
    int seats; // 座位数,私有属性

public:
    // 构造函数,初始化属性
    // 笔者注:我在构造函数的参数变量名前添加 p_ 前缀,用作区分成员变量和参数变量
    Sofa(string p_color, string p_material, int p_seats) : color(p_color), material(p_material), seats(p_seats) {}

    // 公共方法:获取座位数(访问私有属性)
    int getSeats() const {
        return seats;
    }

    // 公共方法:坐的行为
    void sit() const {
        cout << "坐在" << color << "的" << material << "沙发上" << endl;
    }

    // 公共方法:躺的行为
    void lieDown() const {
        if (getSeats() >= 2) {
            cout << "可以躺下" << endl;
        } else {
            cout << "单人沙发无法躺下" << endl;
        }
    }
};

关键点:

  • 类是抽象的:它不是具体的沙发,而是描述沙发“长什么样”和“能做什么”的抽象模板。
  • 属性(Attribute):类的“特征”(如颜色color、材质material)。
  • 方法(Method):类的“行为”(如坐sit()、躺liedown())。
  • 访问控制:通过private关键字隐藏属性(如seats),通过公共方法(如getSeats())控制访问,实现封装。

对象(Object)

类的“实例”

根据设计图纸,工厂生产出具体的沙发。比如:

  • 沙发A:红色、皮质、3座位
  • 沙发B:蓝色、布质、1座位

创建对象

int main() {
    // 创建两个沙发对象(实例化)
    Sofa sofaA("红色", "皮质", 3);
    Sofa sofaB("蓝色", "布质", 1);

    // 调用对象的方法
    sofaA.sit();       // 输出:坐在红色的皮质沙发上
    sofaB.lieDown();   // 输出:单人沙发无法躺下

    return 0;
}

关键点:

  • 对象是具体的:每个对象有自己的属性值(如沙发AsofaA是红色,沙发BsofaB是蓝色)。
  • 实例化:从类创建对象的过程,通过调用构造函数(如 Sofa(...))实现。

封装(Encapsulation)

信息隐藏

沙发的内部结构(如弹簧、填充物)被包裹在布料或皮革下,用户只需知道如何使用沙发(坐、躺),而无需了解内部工作原理

代码中的封装

#include <iostream>
#include <string>
using namespace std;

class Sofa {
private: // 私有访问权限,隐藏内部属性
    string color;
    string material;
    int seats; // 座位数,私有属性

public:
    // 构造函数,初始化属性
    // 笔者注:我在构造函数的参数变量名前添加 p_ 前缀,用作区分成员变量和参数变量
    Sofa(string p_color, string p_material, int p_seats) : color(p_color), material(p_material), seats(p_seats) {}

    // 公共方法:获取座位数(访问私有属性)
    int getSeats() const {
        return seats;
    }

    // 公共方法:坐的行为
    void sit() const {
        cout << "坐在" << color << "的" << material << "沙发上" << endl;
    }

    // 公共方法:躺的行为
    void lieDown() const {
        if (getSeats() >= 2) {
            cout << "可以躺下" << endl;
        } else {
            cout << "单人沙发无法躺下" << endl;
        }
    }
};

关键点

  • 私有属性:用private关键字修饰属性(如colormaterialseats),禁止外部直接访问。
  • 公共接口:通过public方法(如getSeats()sit())提供对外交互的途径,保护数据安全。

核心作用:隐藏内部细节,控制数据访问,避免外部代码直接修改对象状态。

继承(Inheritance)

复用与扩展

你基于“沙发”图纸设计了一款多功能沙发床,它保留了沙发的所有特性(颜色、材质、坐的功能),并新增了展开成床的功能

代码中的继承:

class SofaBed : public Sofa { // 公有继承自 Sofa 类
private:
    double bedLength; // 新增属性:床的长度

public:
    // 构造函数:复用父类初始化逻辑,并添加可指定的bedLength初始化
    SofaBed(string p_color, string p_material, int p_seats, double p_bedLength) : Sofa(p_color, p_material, p_seats), bedLength(p_bedLength) {}
    // 提供另一个构造函数,默认bedLength值为1.8
    SofaBed(string p_color, string p_material, int p_seats) : Sofa(p_color, p_material, p_seats), bedLength(1.8) {}

    // 新增方法:展开成床
    void unfold() const {
        cout << "展开沙发,变成" << bedLength << "米的床" << endl;
    }
};

创建和使用子类对象

int main() {
    SofaBed sofaBedA("白色", "亚麻", 2, 2.0);  // 自动调用构造函数1,将私有成员变量bedLength设为2.0
    SofaBed sofaBedB("灰色", "亚麻", 2);       // 自动调用构造函数2,成员变量bedLength使用默认值1.8

    sofaBedA.sit();       // 继承自父类的方法,输出:坐在白色的亚麻沙发上
    sofaBedA.unfold();    // 子类新增的方法,输出:展开沙发,变成2.0米的床


    sofaBedB.sit();       // 继承自父类的方法,输出:坐在灰色的亚麻沙发上
    sofaBedB.unfold();    // 子类新增的方法,输出:展开沙发,变成1.8米的床

    return 0;
}

关键点

  • 代码复用:子类(SofaBed)继承父类(Sofa)的属性和方法,避免重复编写。
  • 功能扩展:子类可添加新属性(如 bedLength)和新方法(如 unfold()),或重写父类方法(后续章节可深入学习虚函数实现重写)。

多态(Polymorphism)

同一接口,不同实现

你设计了多种类型的家具(沙发、椅子、桌子),它们都有“清洁”的功能,但清洁方式不同

  • 沙发:用吸尘器吸
  • 椅子:用湿布擦
  • 桌子:先用清洁剂再擦

代码中的多态

class Furniture {
public:
    virtual void clean() const = 0; // 纯虚函数,定义通用接口(抽象类)
};

class Sofa : public Furniture {
public:
    void clean() const override { // C++11 及以上支持 override 关键字
        cout << "用吸尘器清洁沙发" << endl;
    }
};

class Chair : public Furniture {
public:
    void clean() const override {
        cout << "用湿布擦拭椅子" << endl;
    }
};

class Table : public Furniture {
public:
    void clean() const override {
        cout << "先用清洁剂喷洒,再用干布擦拭桌子" << endl;
    }
};

统一调用不同对象的方法

int main() {
    // 创建家具对象数组(通过基类指针实现多态)
    Furniture* furnitureList[] = {new Sofa(), new Chair(), new Table()};

    // 遍历调用清洁方法
    for (auto* item : furnitureList) {
        item->clean(); // 同一接口,根据对象实际类型执行不同实现
    }

    // 释放内存(避免内存泄漏)
    for (auto* item : furnitureList) {
        delete item;
    }

    return 0;
}

以上代码将会输出:

用吸尘器清洁沙发
用湿布擦拭椅子
先用清洁剂喷洒,再用干布擦拭桌子

关键点

  • 接口统一:基类(Furniture)通过纯虚函数 clean() 定义统一接口。
  • 动态绑定:子类(SofaChairTable)重写 clean() 方法,运行时根据对象实际类型调用对应实现(需通过基类指针/引用实现)。
  • 抽象类:包含纯虚函数的类(如 Furniture)无法实例化,仅作为基类被继承。

总结

通过家具的例子,带你理解 C++ 面向对象编程(OOP)的四大核心概念:

类与对象:用类组织代码(模板),用对象表示具体事物(实例)。
封装:隐藏内部细节,通过公共接口控制访问,保证数据安全。
继承:复用父类代码,扩展子类功能,实现代码重用与层次化设计。
多态:统一接口定义,不同类实现不同行为,提高代码灵活性和可维护性。

C++ 与 Python 的差异提示

  • C++需要显式声明访问权限(private/public),Python通过双下划线(__)模拟私有属性。
  • C++继承需指定继承方式(如public),Python直接在类名后括号中指定父类。
  • C++多态依赖虚函数(virtual)和基类指针,Python通过动态类型自动实现多态。
  • C++的构造函数必须与类同名Python的构造函数使用__init__方法。

附:C++的三种继承方式

继承类型基类public成员基类protected成员基类private成员
公有继承public子类中为public子类中为protected子类中不可见
保护继承protected子类中为protected子类中为protected子类中不可见
私有继承private子类中为private子类中为private子类中不可见

C++中,类的继承语法如下:

class [子类名字] : [继承类型] [父类名字] { /* ... */ };

// 例如:

class Mammal : public Animal { /* ... */ };

/*
 * 其中,子类名字为Mammal,
 *       继承类型为public(即公有继承),
 *       父类名字为Animal
 */

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇