C++ 类 & 对象(完整教程)

C++ 类 & 对象:从零开始构建你的程序世界

在学习 C++ 的过程中,你可能会遇到一个核心概念——类与对象。它不仅是面向对象编程的基石,更是让代码结构更清晰、可维护性更强的关键。如果你曾经为“如何组织代码”而困扰,那么掌握 C++ 类 & 对象,就像是拿到了一把打开高效编程之门的钥匙。

想象一下,你正在设计一个游戏系统。你需要描述“角色”:有名字、血量、攻击力,还能移动、攻击、受伤。如果用普通变量和函数来处理,代码很快就会变得杂乱无章。而通过类(class),你可以把所有相关数据和行为“打包”成一个完整的“角色”实体——这就是对象。这种封装思想,正是 C++ 类 & 对象的核心魅力。

接下来,我们一步步拆解这个概念,从定义到使用,再到高级特性,带你真正理解它。


类的定义:蓝图与实体的分界

在现实世界中,我们不会直接“造”一个房子,而是先画一张图纸。这张图纸就是“蓝图”,它规定了房子的结构、门窗位置、楼层布局。在 C++ 中,类就相当于这个蓝图。

class Character {
public:
    // 成员变量:描述角色的属性
    std::string name;
    int health;
    int attackPower;

    // 成员函数:描述角色的行为
    void introduce() {
        std::cout << "我是 " << name << ",血量 " << health 
                  << ",攻击力 " << attackPower << std::endl;
    }

    void takeDamage(int damage) {
        health -= damage;
        if (health < 0) health = 0;
        std::cout << name << " 受到 " << damage << " 点伤害,剩余血量:" << health << std::endl;
    }
};

这段代码定义了一个名为 Character 的类。注意几点:

  • class 关键字用于声明类。
  • public: 是访问控制符,表示其后的成员可以被外部直接访问(后续会讲私有和保护)。
  • 成员变量(如 namehealth)保存对象的状态。
  • 成员函数(如 introducetakeDamage)定义对象的行为。

这只是一个“模板”,还不能直接使用。你必须根据这个模板创建具体的“对象”。


创建对象:从蓝图到现实

有了蓝图,就可以造出实际的房子了。在 C++ 中,创建对象叫做“实例化”。

int main() {
    // 创建一个 Character 类的对象
    Character player;

    // 给对象的成员变量赋值
    player.name = "勇者小明";
    player.health = 100;
    player.attackPower = 25;

    // 调用对象的方法
    player.introduce();        // 输出:我是 勇者小明,血量 100,攻击力 25
    player.takeDamage(30);     // 输出:勇者小明 受到 30 点伤害,剩余血量:70

    return 0;
}

这里我们创建了一个名为 player 的对象,它是 Character 类的一个实例。通过点操作符 .,我们可以访问对象的成员变量和成员函数。

💡 小贴士:每个对象都有自己独立的数据副本。比如再创建一个 Character enemy;,它的 namehealthplayer 完全无关。


构造函数:对象的“出生仪式”

你有没有想过,每次创建对象时,都手动赋值属性很麻烦?有没有一种方式,让对象在创建时就自动完成初始化?

答案是:构造函数。

构造函数是一种特殊的成员函数,名字与类名相同,且没有返回类型(连 void 都不能写)。它在对象创建时自动调用。

class Character {
public:
    std::string name;
    int health;
    int attackPower;

    // 构造函数:初始化对象
    Character(std::string n, int h, int a) {
        name = n;
        health = h;
        attackPower = a;
        std::cout << "角色 " << name << " 已出生!" << std::endl;
    }

    void introduce() {
        std::cout << "我是 " << name << ",血量 " << health 
                  << ",攻击力 " << attackPower << std::endl;
    }

    void takeDamage(int damage) {
        health -= damage;
        if (health < 0) health = 0;
        std::cout << name << " 受到 " << damage << " 点伤害,剩余血量:" << health << std::endl;
    }
};

现在,创建对象时可以这样写:

int main() {
    // 直接在创建时传入参数,构造函数自动执行
    Character player("勇者小明", 100, 25);
    Character enemy("暗影刺客", 80, 30);

    player.introduce();  // 输出:我是 勇者小明,血量 100,攻击力 25
    enemy.introduce();   // 输出:我是 暗影刺客,血量 80,攻击力 30

    return 0;
}

构造函数让对象的初始化变得简洁又安全,是 C++ 类 & 对象中非常重要的组成部分。


访问控制:保护你的数据

在上面的例子中,所有成员都是 public,意味着外部可以随意修改对象的数据。这在实际项目中很危险。

比如,如果有人把 player.health = -100;,那就出问题了。

为了解决这个问题,C++ 引入了访问控制符:privateprotected

class Character {
private:
    // 私有成员:只能在类内部访问
    std::string name;
    int health;
    int attackPower;

public:
    // 公有成员:外部可以访问
    Character(std::string n, int h, int a) {
        name = n;
        health = h;
        attackPower = a;
    }

    // 提供公有接口来访问私有数据
    void introduce() {
        std::cout << "我是 " << name << ",血量 " << health 
                  << ",攻击力 " << attackPower << std::endl;
    }

    void takeDamage(int damage) {
        if (damage < 0) {
            std::cout << "伤害值不能为负数!" << std::endl;
            return;
        }
        health -= damage;
        if (health < 0) health = 0;
        std::cout << name << " 受到 " << damage << " 点伤害,剩余血量:" << health << std::endl;
    }

    // 提供 getter 和 setter 方法
    int getHealth() const {
        return health;
    }

    void setHealth(int h) {
        if (h < 0) h = 0;
        health = h;
    }
};
  • private: 成员只能在类内部使用。
  • public: 成员可以被外部调用。
  • const 修饰的函数表示该函数不会修改对象状态,适用于 getter。

这样,外部无法直接修改 health,但可以通过 setHealth() 安全地设置值。这就是封装的力量。


类的组合与继承:构建复杂系统

在真实项目中,一个类往往不是孤立存在的。比如,一个 Player 类可能包含一个 Weapon 对象,这就是组合。

class Weapon {
public:
    std::string name;
    int damage;

    Weapon(std::string n, int d) : name(n), damage(d) {}
};

class Player {
private:
    std::string name;
    int health;
    Weapon weapon;  // 组合:Player 拥有一个 Weapon 对象

public:
    Player(std::string n, int h, std::string wName, int wDamage)
        : name(n), health(h), weapon(wName, wDamage) {}

    void attack() {
        std::cout << name << " 使用 " << weapon.name 
                  << " 发动攻击,造成 " << weapon.damage << " 点伤害!" << std::endl;
    }
};

这里,Player 类中嵌套了一个 Weapon 类的对象。这种“整体-部分”关系,就是组合。

而继承,则是“是一种”的关系。比如:

class Warrior : public Character {
public:
    int rage;  // 战士特有属性

    Warrior(std::string n, int h, int a) : Character(n, h, a), rage(0) {}

    void useRage() {
        if (rage > 0) {
            rage--;
            std::cout << name << " 消耗怒气,攻击力提升!" << std::endl;
        }
    }
};

WarriorCharacter 的子类,继承了所有 Character 的成员,并添加了新功能。这极大提高了代码复用性。


实际应用:模拟一个战斗系统

让我们整合所学,写一个简单的战斗系统:

#include <iostream>
#include <string>

class Character {
protected:
    std::string name;
    int health;
    int attackPower;

public:
    Character(std::string n, int h, int a) : name(n), health(h), attackPower(a) {}

    virtual void attack() {
        std::cout << name << " 发动普通攻击,造成 " << attackPower << " 点伤害!" << std::endl;
    }

    void takeDamage(int damage) {
        health -= damage;
        if (health < 0) health = 0;
        std::cout << name << " 受到 " << damage << " 点伤害,剩余血量:" << health << std::endl;
    }

    bool isAlive() const {
        return health > 0;
    }

    std::string getName() const {
        return name;
    }
};

class Mage : public Character {
public:
    int mana;

    Mage(std::string n, int h, int a, int m) : Character(n, h, a), mana(m) {}

    void castSpell() {
        if (mana >= 20) {
            mana -= 20;
            std::cout << name << " 施放火球术,造成 50 点伤害!" << std::endl;
        } else {
            std::cout << name << " 法力不足,无法施法!" << std::endl;
        }
    }

    void attack() override {
        if (mana >= 20) {
            castSpell();
        } else {
            std::cout << name << " 法力不足,只能普通攻击!" << std::endl;
            Character::attack();
        }
    }
};

int main() {
    Mage player("火法师莉莉", 80, 20, 50);

    while (player.isAlive()) {
        std::cout << "选择行动:1. 普通攻击 2. 施法" << std::endl;
        int choice;
        std::cin >> choice;

        if (choice == 1) {
            player.attack();
        } else if (choice == 2) {
            player.castSpell();
        } else {
            std::cout << "无效选择!" << std::endl;
        }
    }

    std::cout << "战斗结束!" << std::endl;
    return 0;
}

这个例子展示了:

  • 继承与多态(virtualoverride
  • 构造函数初始化列表
  • 成员函数的重写
  • 实际交互逻辑

C++ 类 & 对象 的强大,正在于此——它让你能像搭积木一样,构建复杂而可靠的系统。


总结:掌握类与对象,就是掌握 C++ 的灵魂

C++ 类 & 对象 不只是一个语法概念,它是一种思维方式。它教会你如何将现实世界的问题抽象成代码模型,如何封装数据、控制访问、复用逻辑。

从一个简单的 Character 类开始,到组合、继承、多态,每一步都在提升你的编程能力。当你能熟练使用类与对象时,你会发现代码不再杂乱,而是结构清晰、易于扩展。

记住:写代码不是为了“能跑”,而是为了让“好维护、好扩展”。C++ 类 & 对象,就是通往这一境界的必经之路。

现在,不妨动手写一个属于你的类吧——也许是“汽车”、“学生”、“银行账户”。你会发现,编程的乐趣,就藏在这些小小的对象之中。