类与对象的理解

一、从现实世界到程序世界

我们熟悉的现实世界中,一切事物都是对象。对象可以是有形的,比如房屋、汽车、飞机、动物、植物;也可以是无形的,比如一项计划、一个订单、一次交易。对象可以是一个简单的个体(比如一个人),也可以是诸多其他对象组合而成的复杂体(比如一个公司由多个部门组成,每个部门又由许多人组成)。

对相似的对象进行抽象,找出其共同的属性和行为,便构成了一种类型。例如,张三、李四、王五都是具体的人(对象),对他们抽象后可以得到”人”这个类型——每个人都有姓名、年龄、身高等属性,也都有吃饭、走路、说话等行为。

编写程序的目的是描述与解决现实世界中的问题。面向对象程序设计的第一步,就是将现实世界中的对象和类如实反映到程序中。作为一种面向对象的程序设计语言,C++ 支持这种抽象:将抽象后的数据(属性)和函数(行为)封装在一起,便构成了 C++ 的”类”(class)。

二、面向对象程序设计的四个主要特点

特点核心思想通俗理解
抽象提取同类对象的共同特征,忽略非本质细节从具体的人中提炼出”人”这个概念
封装将数据和对数据的操作捆绑在一起,隐藏内部细节,对外提供接口把属性和方法装进一个”盒子”,只留几个按钮在外面
继承在已有类的基础上扩展出新类,复用已有代码学生是人的一种,自动拥有人的所有特征
多态同一操作作用于不同对象,可以产生不同的执行结果同样说”叫”,狗叫是”汪汪”,猫叫是”喵喵”

这四个特点将在后续章节中逐一展开讲解。

三、抽象

抽象(Abstraction)是指从具体事物中提取出我们关心的特征,忽略不相关的细节,形成对该事物的抽象描述。

现实世界中的”学生”:有学号、姓名、年龄、专业、成绩等属性,也有选课、考试、打印成绩单等行为。在程序中,我们关心哪些特征,就提取哪些,不关心的(比如鞋码、发色)可以忽略。

抽象的结果就是”类”——类是对一组具有相同属性和行为的对象的抽象描述。

现实世界:  张三(具体学生)  →  抽象  →  "学生"类
程序世界:  Student 类       →  实例化  →  Student 对象 s1Code language: JavaScript (javascript)

四、封装

封装(Encapsulation)是将抽象得到的数据成员(属性)和成员函数(行为)捆绑在一起,形成一个有机的整体(类)。同时,封装还隐藏了对象的内部实现细节,对外只暴露有限的接口(公有成员函数),外部只能通过接口来访问对象。

封装的好处:

  • 数据保护:外部不能随意修改对象内部的数据,只能通过规定的方法修改,避免数据被破坏。
  • 降低耦合:外部只需要知道”能做什么”,不需要知道”怎么做”,类内部实现改变不影响外部代码。
  • 提高可维护性:类的修改局限在类内部,不影响程序其他部分。

五、代码示例

以下代码演示了如何用 C++ 定义一个简单的类,体现抽象和封装的思想:

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

// ===== 定义一个"学生"类 =====
class Student
{
private:                        // 私有成员:外部不能直接访问
    string name;                // 姓名
    int age;                    // 年龄
    double score;               // 成绩

public:                         // 公有接口:外部通过它们访问对象
    // 设置学生信息
    void setName(string n)
    {
        name = n;
    }

    void setAge(int a)
    {
        if (a > 0 && a < 150)   // 封装了数据校验逻辑
            age = a;
        else
            age = 0;
    }

    void setScore(double s)
    {
        if (s >= 0 && s <= 100)
            score = s;
        else
            score = 0;
    }

    // 获取学生信息
    string getName()
    {
        return name;
    }

    int getAge()
    {
        return age;
    }

    double getScore()
    {
        return score;
    }

    // 行为:显示信息
    void display()
    {
        cout << "姓名:" << name << ",年龄:" << age 
             << ",成绩:" << score << endl;
    }

    // 行为:判断是否及格
    bool isPass()
    {
        return score >= 60;
    }
};

int main()
{
    // 创建 Student 类的对象(实例化)
    Student s1;
    Student s2;

    // 通过公有接口设置对象数据
    s1.setName("张三");
    s1.setAge(20);
    s1.setScore(85.5);

    s2.setName("李四");
    s2.setAge(19);
    s2.setScore(58.0);

    // 通过公有接口访问对象
    s1.display();
    s2.display();

    cout << s1.getName() << (s1.isPass() ? " 及格" : " 不及格") << endl;
    cout << s2.getName() << (s2.isPass() ? " 及格" : " 不及格") << endl;

    return 0;
}Code language: PHP (php)

分析:

  • Student 类是对”学生”这一现实事物的抽象:提取了姓名、年龄、成绩三个属性,以及设置和获取信息、显示、判断是否及格等行为。
  • 数据成员 name、age、score 被声明为 private,外部不能直接访问,只能通过 public 的成员函数间接访问,这就是封装。
  • setAge 和 setScore 中加入了数据校验逻辑,防止非法数据进入对象内部,体现了封装对数据的保护作用。
  • main 函数中通过 Student s1; 创建了 Student 类的对象(实例),通过对象调用成员函数完成操作。

六、类与对象的关系

概念说明类比
类(class)抽象的模板,描述一类对象的共同特征建筑图纸
对象(object)类的具体实例,占有实际内存空间按图纸建好的房子
实例化从类创建对象的过程按图纸施工
成员函数类中定义的函数,描述对象的行为房子的功能(开门、开灯)
数据成员类中定义的变量,描述对象的属性房子的属性(面积、朝向)

一个类可以创建多个对象,每个对象拥有独立的数据成员副本,但共享同一份成员函数的代码。

七、注意事项

  • 类是用户自定义的数据类型,定义后不占用内存(类似于 int 这个类型本身不占内存),只有创建对象时才分配内存。
  • 类的定义以分号 ; 结尾,不能省略。
  • private 和 public 是访问限定符。private 成员只能在类内部访问,public 成员在类内外均可访问。默认情况下(不写访问限定符时),class 的成员是 private 的。
  • 成员函数可以在类体内定义(隐式内联),也可以在类体内声明、类体外定义(需加 类名:: 前缀)。
  • 封装的核心不是”把东西藏起来”,而是”合理地暴露接口、保护数据”。不要为了封装而把所有成员都设为 private,要根据设计需求决定访问级别。

八、常见错误

1. 忘记类定义末尾的分号
class Student
{
    // ...
}              // 错误:缺少分号Code language: JavaScript (javascript)
2. 直接访问私有成员
Student s;
s.name = "张三";    // 错误:name 是 private 成员Code language: JavaScript (javascript)

解决:通过公有成员函数 s.setName("张三");

3. 类体外定义成员函数忘记加类名限定符
void display()     // 错误:不知道是哪个类的 display
{
    cout << name << endl;
}Code language: JavaScript (javascript)

正确写法:

void Student::display()
{
    cout << name << endl;
}Code language: JavaScript (javascript)
4. 混淆类和对象
Student.age = 20;   // 错误:age 是对象的成员,不是类的成员Code language: JavaScript (javascript)

正确写法:

Student s;
s.setAge(20);Code language: CSS (css)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注