文章

【GESP】C++六级考试大纲知识点梳理, (6) 面向对象编程(OOP)基础

GESP C++六级官方考试大纲中,第6条考点标志着我们编程思维的一次重要跃迁——从“面向过程”转向“面向对象”。

(6)掌握面向对象的思想,了解封装、继承、多态的基本概念,并掌握类的创建和基本的使用方法。

本人也是边学、边实验、边总结,且对考纲深度和广度的把握属于个人理解。因此本文更多的不是一个教程,而是个人知识梳理,如有遗漏、疏忽,欢迎指正、交流。

面向对象编程(Object-Oriented Programming,简称 OOP)听起来很高大上,其实它最贴近我们的真实世界。如果说“面向过程”是像做菜一样一步步按照食谱执行,那么“面向对象”就是组装一台精密的机器,每个零件(对象)都有自己的功能,组合起来完成复杂的任务。对于初学者来说,理解“类”与“对象”的关系是关键。

六级考点系列:


一、什么是面向对象 (OOP)?

在学习 C++ 的前几个级别时,我们写的代码大多是面向过程 (Procedure Oriented) 的。 比如解决“把大象装进冰箱”这个问题,面向过程的思维是:

  1. 打开冰箱门();
  2. 拿起大象();
  3. 塞进冰箱();
  4. 关闭冰箱门();

我们关注的是动作(函数) 的执行顺序。

面向对象 (Object Oriented) 的思维则是:我们需要两个“对象”:大象冰箱

  • 冰箱这个对象,应该具备“开门”、“关门”、“装东西”的功能。
  • 大象这个对象,应该具备“移动”、“体积”等属性。

然后我们指挥对象工作:

冰箱.打开() -> 冰箱.装入(大象) -> 冰箱.关闭()

核心区别

  • 面向过程:关注怎么做(Step by Step)。适合简单逻辑。
  • 面向对象:关注谁来做(Who does what)。适合复杂系统,方便管理和扩展。

二、类 (Class) 与 对象 (Object)

这是 OOP 中最核心的一对概念,一定要区分清楚。

2.1 概念比喻

  • 类 (Class):是图纸、是模具。它规定了某一类事物应该长什么样(属性),能干什么(方法)。它是一个抽象的概念,不占用内存空间
  • 对象 (Object):是房子、是饼干。它是根据图纸造出来的实物,是模具印出来的成品。它是具体的,占用内存空间

例子

  • “人类”是一个(Class)。
  • “坐在你旁边的那个叫小明的同学”是一个对象(Object)。

2.2 面向对象的语法总结

在 C++ 中定义和使用类,我们会用到一些核心的关键字和符号:

关键字/符号作用示例
class定义一个类(模具)。class Student { ... };
public:访问权限修饰符,表示其后的成员是公开的,外部可以直接访问。public: string name;
private:访问权限修饰符,表示其后的成员是私有的,只有类内部才能访问。private: int password;
string, int定义成员变量(属性)的数据类型。string name;
void定义成员函数(方法)的返回值类型。void introduce() { ... };
. (点操作符)用来访问对象的属性或调用对象的方法。stu1.name = "小明";
:: (作用域解析符)用于在类外部定义成员函数,或访问命名空间成员void Student::introduce() { ... }; (类外定义方法) \ std::cout (访问命名空间 std 中的 cout 对象)

注意:在调用对象的普通(非静态)方法时,我们使用 . (点操作符),例如 stu1.introduce();。作用域解析符 :: 主要用于类外部定义成员函数,或者访问特定命名空间中的成员(比如 std::cout 中的 std 就是一个命名空间)。

2.2.1 类定义语法模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class ClassName {
private:
    // 私有属性(数据),只能在类内部访问
    DataType privateMember1;
    DataType privateMember2;

public:
    // 公有属性(数据),外部可直接访问,但通常不建议
    DataType publicMember1;

    // 构造函数:对象创建时自动调用,用于初始化
    ClassName(ParameterType param1, ...) {
        // 初始化成员变量
    }

    // 析构函数:对象销毁时自动调用,用于清理资源
    ~ClassName() {
        // 清理工作
    }

    // 公有方法(函数),外部可调用,实现类的行为
    ReturnType publicMethod1(ParameterType param1, ...) {
        // 方法实现
        return value;
    }

    // 私有方法(函数),只能在类内部调用,辅助实现公有方法
private:
    ReturnType privateMethod1(...) {
        // 方法实现
    }
};

2.3 C++ 代码实现

在 C++ 中,我们用 class 关键字来定义类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string>
using namespace std;

// 1. 定义一个类:Student (学生)
class Student {
public: // 访问权限:公开的
    // --- 属性 (成员变量) ---
    string name;
    int age;
    int score;

    // --- 行为 (成员函数) ---
    void introduce(); // 声明:方法原型,实现在类外部

    void study() {
        score++;
        cout << name << "正在努力学习,分数+1,现在分数是:" << score << endl;
    }
};

// 在类外部使用作用域解析符 :: 实现 introduce 方法
void Student::introduce() {
    cout << "大家好,我是" << name << ",今年" << age << "岁。" << endl;
}

int main() {
    // 2. 创建对象 (实例化)
    Student stu1;  // 创建了一个叫 stu1 的对象
    
    // 3. 使用对象 (访问属性和方法)
    stu1.name = "小明";
    stu1.age = 13;
    stu1.score = 90;
    
    stu1.introduce(); // 调用方法
    stu1.study();     // 调用方法
    
    // 创建另一个对象
    Student stu2;
    stu2.name = "小红";
    stu2.introduce(); // 小红和小明互不干扰

    return 0;
}

三、OOP 三大特性

考试大纲明确要求了解:封装继承多态

3.1 封装 (Encapsulation)

含义:把数据(属性)和操作数据的方法(函数)捆绑在一起,并且隐藏内部实现的细节,只暴露必要的接口给外部使用。

比喻:就像电视机

  • 隐藏细节:你看不见里面的电路板、显像管(这就是 private 私有成员)。你也不能直接用手去拨动里面的电线,否则会触电或弄坏电视。
  • 暴露接口:电视机提供了遥控器按钮(这就是 public 公有成员)。你只需要按“开机”、“换台”,不需要知道电路是怎么工作的。

C++ 关键字

  • public (公有):谁都能访问。
  • private (私有):只有类自己内部能访问,外部(main函数里)不能直接改。
  • protected (保护):主要用于继承,子类能访问。

为什么要封装? 安全!防止外部代码随意篡改对象内部的敏感数据。

3.2 继承 (Inheritance)

含义:允许一个新的类(子类/派生类)获取现有类(父类/基类)的属性和方法。

比喻

爸爸(父类)有亿万家产(属性)和经商技巧(方法)。 儿子(子类)继承了爸爸,天生就有了家产和技巧,不用从头开始奋斗。同时,儿子还可以有自己独特的爱好(扩展新功能)。

3.2.1 继承的语法规则

在 C++ 中,使用 : 符号来表示继承关系。基本语法如下:

1
2
3
class 子类名 : 访问修饰符 父类名 {
    // 子类特有的属性和方法
};
  • 子类名:正在定义的新的类。
  • 访问修饰符:指定继承方式,可以是 publicprotectedprivate
    • public 继承 (最常用):父类的 public 成员在子类中依然是 public;父类的 protected 成员在子类中依然是 protected。父类的 private 成员子类不能直接访问。
    • protected 继承:父类的 publicprotected 成员在子类中都变为 protected
    • private 继承:父类的 publicprotected 成员在子类中都变为 private
  • 父类名:被继承的那个类。

简单来说,考试中我们通常使用 public 继承,它表示“儿子”完全公开地继承“爸爸”的衣钵,该公开的还是公开,该保护的还是保护。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 父类:动物
class Animal {
public:
    string name;
    void eat() {
        cout << name << " 正在吃东西..." << endl;
    }
};

// 子类:狗 (继承自 Animal)
class Dog : public Animal { 
public:
    void bark() { // 子类特有的方法
        cout << "汪汪汪!" << endl;
    }
};

int main() {
    Dog myDog;
    myDog.name = "旺财"; 
    myDog.eat();  // 继承自父类的方法,可以直接用!
    myDog.bark(); // 自己的方法
    return 0;
}

3.3 多态 (Polymorphism)

含义:同一个操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。简单说就是 “多种形态”

比喻:不管是理发师、厨师还是园丁,都有一个动作叫 “Cut (切/剪)”

  • 对理发师说“Cut” -> 他会剪头发。
  • 对厨师说“Cut” -> 他会切菜。
  • 对园丁说“Cut” -> 他会修剪草坪。

同一个命令,不同的人(对象)做出了不同的反应,这就是多态。

在 C++ 中,多态通常通过虚函数 (virtual function) 来实现。当父类的指针指向子类对象时,调用同一个函数,会执行子类特定的版本。

注:六级考试对多态的要求通常是“了解概念”,具体的虚函数语法和动态绑定机制可能在更高级别深入考察,但理解其思想对于设计程序非常有帮助。


四、构造函数与析构函数

这是类中两个特殊的函数,就像人的“出生”和“去世”。

4.1 构造函数 (Constructor)

  • 函数名:与类名完全相同。
  • 返回值没有返回值(连 void 都不写)。
  • 时机:对象被创建时自动调用。
  • 作用初始化。给对象的属性赋初值,比如刚买的手机电量默认是 100%。

4.2 析构函数 (Destructor)

  • 函数名~ + 类名(比如 ~Student)。
  • 返回值:没有返回值。
  • 时机:对象被销毁时(比如函数结束,局部变量失效时)自动调用。
  • 作用清理善后。比如释放申请的内存,关闭打开的文件等。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <string>
using namespace std;
class Hero {
   public:
    string name;

    // 构造函数
    Hero(string n) {
        name = n;
        cout << name << " 英雄降临!(构造函数被调用)" << endl;
    }

    // 析构函数
    ~Hero() { cout << name << " 英雄牺牲了... (析构函数被调用)" << endl; }
};

int main() {
    {
        Hero h1("盖伦");  // 创建对象,输出:盖伦 英雄降临!
    }  // 出了这个大括号,h1 作用域结束,对象销毁, // 输出:盖伦 英雄牺牲了...
    cout << "----" << endl;

    return 0;
}

输出:

1
2
3
盖伦 英雄降临!(构造函数被调用)
盖伦 英雄牺牲了... (析构函数被调用)
----

五、备考总结

对于 GESP 六级考生,面向对象部分重点掌握以下几点:

  1. 语法层面
    • 熟练掌握 class 的定义。
    • 会定义成员变量和成员函数。
    • 理解 publicprivate 的区别。
    • 会编写简单的构造函数进行初始化。
    • 会实例化对象并调用其成员 (. 操作符)。
  2. 概念层面
    • 能够用自己的话解释“封装、继承、多态”。
    • 理解“类是图纸,对象是实物”。
  3. 结构体 vs 类
    • 在 C++ 中,structclass 极其相似。
    • 唯一核心区别:struct 默认权限是 publicclass 默认权限是 private
    • 考试中如果遇到简单的属性组合(如坐标点 x, y),用 struct 依然很方便;但如果涉及到复杂的行为管理,建议尝试用 class

面向对象是一种编程世界观,掌握它,你的代码将从“杂乱的脚本”进化为“严密的系统”。加油!


附录:结构体 (struct) 与类 (class) 的异同

这是一个非常经典且在面试和考试中常被问到的问题。在 C++ 中,struct(结构体)和 class(类)的区别既微小又深刻,这主要源于 C++ 的历史包容性。

简而言之:在技术上,它们几乎一模一样;但在设计意图和默认行为上,有两点核心区别。

1. 技术上的区别(语法层面)

在 C++ 中,structclass 的功能几乎是完全等价的。struct 也可以有构造函数、析构函数、成员函数、继承、多态等。

唯一的区别在于默认的访问权限

特性struct (结构体)class (类)
成员默认权限public (公有)private (私有)
继承默认权限public (公有继承)private (私有继承)

代码对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct A {
    int x; // 默认为 public
};

class B {
    int y; // 默认为 private
};

int main() {
    A a;
    a.x = 10; // ✅ OK,外部可以直接访问

    B b;
    // b.y = 10; // ❌ Error,y 是私有的,不可访问
    // 如果要访问 private 成员,需要通过 public 方法
    return 0;
}

2. 为什么要设计两种模式?(历史与设计哲学)

既然功能一样,为什么不直接废除 struct 或者只用 class 呢?这主要归功于 C++ 之父 Bjarne Stroustrup 的设计哲学:“不破坏现有的代码” (Backward Compatibility)

A. 兼容 C 语言 (C Compatibility)

C++ 被设计为 C 语言的超集。

  • 在 C 语言中,struct 只是一个数据的集合,所有成员天然都是公开的(没有 private 的概念)。
  • 为了让数百万行现有的 C 代码能在 C++ 编译器下直接编译通过,C++ 中的 struct 必须保持“默认公有”这一特性。如果改成默认私有,所有的 C 程序都会报错。

B. 强调面向对象封装 (Encapsulation)

  • 引入 class 是为了支持面向对象编程 (OOP)。
  • OOP 的核心原则之一是封装——即默认隐藏内部细节,只暴露接口。
  • 因此,class 采用了“默认私有”的策略,这是一种防御性编程的思维:除非你明确说这个是可以公开的,否则它就是安全的、隐藏的。

3. 我们该如何选择?(最佳实践)

虽然你可以在 struct 里写复杂的逻辑,也可以在 class 里全写 public,但为了代码的可读性和规范性,业界通常遵循以下约定:

使用 struct 的场景

  • 纯数据集合 (POD - Plain Old Data):仅仅是为了把几个数据捆绑在一起,不包含复杂的逻辑或私有变量。
  • 例如:二维坐标点 Point { int x; int y; },颜色 Color { int r; int g; int b; }
  • 作为“大号”参数包:函数参数太多时,打包成一个 struct 传递。

使用 class 的场景

  • 真正的“对象”:包含数据(属性)和行为(方法)。
  • 需要封装:有私有成员,不希望外部直接修改内部数据(例如学生的分数不能随意被随意改为负数,需要通过函数修改)。
  • 涉及继承和多态:构建复杂的类层次结构。

总结

  • Struct 是为了兼容过去(C语言习惯,数据公开)。
  • Class 是为了规范未来(OOP习惯,数据隐藏)。
  • 考试中如果只涉及简单的 x, y 坐标存储,写 struct 会省去写 public: 的麻烦;如果是写一个完整的系统,请使用 class

所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code

GESP 学习专题站:GESP WIKI

luogu-”系列题目可在洛谷题库进行在线评测。

bcqm-”系列题目可在编程启蒙题库进行在线评测。

欢迎加入Java、C++、Python技术交流QQ群(982860385),大佬免费带队,有问必答

欢迎加入C++ GESP/CSP认证学习QQ频道,考试资源总结汇总

欢迎加入C++ GESP/CSP学习交流QQ群(688906745),考试认证学员交流,互帮互助

GESP/CSP 认证学习微信公众号
GESP/CSP 认证学习微信公众号
本文由作者按照 CC BY-NC-SA 4.0 进行授权