类的概念及应用

面向对象编程基础

类的基本概念

类(Class)是C++面向对象编程的核心概念,它是一种用户自定义的数据类型,将数据和操作数据的函数封装在一起。

类的基本组成

  • 成员变量(属性):存储数据的状态
  • 成员函数(方法):操作数据的行为
  • 访问控制:public、private、protected
  • 构造函数/析构函数:对象创建和销毁时的操作

类的基本语法


#include <iostream>
using namespace std;

// 定义一个类
class Point {
private:    // 私有成员,只能在类内部访问
    int x;
    int y;

public:     // 公有成员,可以在任何地方访问
    // 构造函数
    Point(int x = 0, int y = 0) {
        this->x = x;
        this->y = y;
    }

    // 成员函数
    void print() {
        cout << "Point(" << x << ", " << y << ")" << endl;
    }

    // Getter函数
    int getX() { return x; }
    int getY() { return y; }

    // Setter函数
    void setX(int x) { this->x = x; }
    void setY(int y) { this->y = y; }
};

int main() {
    Point p1(3, 4);    // 创建对象
    Point p2;         // 使用默认值创建对象

    p1.print();       // Point(3, 4)
    p2.print();       // Point(0, 0)

    p2.setX(10);
    p2.setY(20);
    p2.print();       // Point(10, 20)

    return 0;
}
                

访问控制

访问修饰符 含义 可访问范围
public 公有 任何地方都可以访问
private 私有 只有类内部可以访问
protected 保护 类内部和派生类可以访问
Point 类结构
- int x
- int y
+ Point(int x, int y)
+ void print()
+ int getX()
+ void setX(int x)

构造函数与析构函数


class Student {
private:
    string name;
    int age;

public:
    // 构造函数:对象创建时自动调用
    Student(string n, int a) {
        name = n;
        age = a;
        cout << "构造函数被调用: " << name << endl;
    }

    // 拷贝构造函数
    Student(const Student& other) {
        name = other.name;
        age = other.age;
        cout << "拷贝构造函数被调用" << endl;
    }

    // 析构函数:对象销毁时自动调用
    ~Student() {
        cout << "析构函数被调用: " << name << endl;
    }

    void show() {
        cout << name << ", " << age << "岁" << endl;
    }
};

int main() {
    Student s1("张三", 18);  // 调用构造函数
    s1.show();

    Student s2 = s1;         // 调用拷贝构造函数
    s2.show();

    return 0;
    // 函数结束时,s2和s1依次调用析构函数
}
                

执行流程

  1. 创建 s1 对象 → 调用构造函数
  2. 创建 s2 对象(拷贝s1)→ 调用拷贝构造函数
  3. 函数返回 → s2 调用析构函数
  4. s1 调用析构函数

this指针

this 指针指向当前对象本身,用于区分成员变量和参数。


class Rectangle {
private:
    int width;
    int height;

public:
    Rectangle(int width, int height) {
        this->width = width;    // this->width 成员变量
        this->height = height;  // height 参数
    }

    // 链式调用
    Rectangle& setWidth(int width) {
        this->width = width;
        return *this;  // 返回当前对象的引用
    }

    Rectangle& setHeight(int height) {
        this->height = height;
        return *this;
    }

    int getArea() {
        return width * height;
    }
};

int main() {
    Rectangle r(10, 20);

    // 链式调用
    r.setWidth(5).setHeight(10);
    cout << r.getArea() << endl;  // 50

    return 0;
}
                

内存布局演示

点击按钮观察对象在内存中的布局:

点击按钮查看内存布局

实用示例:分数类


#include <algorithm>
using namespace std;

class Fraction {
private:
    int numerator;    // 分子
    int denominator;  // 分母

    // 求最大公约数
    int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    // 约分
    void reduce() {
        int g = gcd(abs(numerator), abs(denominator));
        numerator /= g;
        denominator /= g;
        if (denominator < 0) {
            numerator = -numerator;
            denominator = -denominator;
        }
    }

public:
    Fraction(int num = 0, int den = 1) {
        if (den == 0) {
            cout << "Error: Denominator cannot be zero!" << endl;
            numerator = 0;
            denominator = 1;
        } else {
            numerator = num;
            denominator = den;
            reduce();
        }
    }

    void print() {
        cout << numerator << "/" << denominator << endl;
    }

    // 转换为浮点数
    double toDouble() {
        return (double)numerator / denominator;
    }

    // 加法
    Fraction add(const Fraction& other) {
        int num = numerator * other.denominator + other.numerator * denominator;
        int den = denominator * other.denominator;
        return Fraction(num, den);
    }
};

int main() {
    Fraction f1(3, 4);   // 3/4
    Fraction f2(1, 2);   // 1/2

    Fraction f3 = f1.add(f2);  // 3/4 + 1/2 = 5/4

    f1.print();  // 3/4
    f2.print();  // 1/2
    f3.print();  // 5/4

    cout << f3.toDouble() << endl;  // 1.25

    return 0;
}
                

最佳实践

编写类的建议

  • 封装:将成员变量设为private,通过public函数访问
  • 构造函数:初始化所有成员变量
  • const成员函数:不修改对象状态的函数加上const
  • 单职责:一个类只做一件事
  • 命名规范:使用有意义的名称