跳转至

类与对象

📖 章节简介

本章将介绍C++的面向对象编程,包括类定义、构造函数、析构函数和成员函数的使用。

UML类图示例

上图展示了典型UML类图结构,便于理解类、属性与对象关系。

🏷️ 类的定义

1. 基本类

C++
// 基本类
#include <iostream>
#include <string>
using namespace std;

class Person {
private:
    string name;
    int age;

public:
    // 构造函数
    Person() {
        name = "匿名";
        age = 0;
    }

    Person(string n, int a) {
        name = n;
        age = a;
    }

    // 成员函数
    void introduce() {
        cout << "我叫" << name << ",今年" << age << "岁" << endl;
    }

    void setName(string n) {
        name = n;
    }

    void setAge(int a) {
        age = a;
    }

    string getName() const {
        return name;
    }

    int getAge() const {
        return age;
    }
};

int main() {
    // 创建对象
    Person person1;
    Person person2("张三", 25);

    // 调用成员函数
    person1.introduce();
    person2.introduce();

    // 访问成员变量(通过getter/setter)
    person2.setName("李四");
    person2.setAge(30);
    cout << "\n修改后:" << endl;
    person2.introduce();

    return 0;
}

2. 构造函数

C++
// 构造函数
#include <iostream>
#include <string>
using namespace std;

class Student {
private:
    string name;
    int age;
    string className;

public:
    // 默认构造函数
    Student() {
        name = "匿名";
        age = 0;
        className = "未分配";
    }

    // 参数化构造函数
    Student(string n, int a, string c) {
        name = n;
        age = a;
        className = c;
    }

    // 拷贝构造函数
    Student(const Student& other) {
        name = other.name;
        age = other.age;
        className = other.className;
    }

    // 析构函数
    ~Student() {
        cout << "学生对象被销毁: " << name << endl;
    }

    // 成员函数
    void display() {
        cout << "姓名: " << name << endl;
        cout << "年龄: " << age << endl;
        cout << "班级: " << className << endl;
    }
};

int main() {
    // 使用不同构造函数创建对象
    Student student1;
    Student student2("张三", 20, "计算机1班");
    Student student3 = student2;  // 使用拷贝构造函数

    // 调用成员函数
    cout << "student1:" << endl;
    student1.display();

    cout << "\nstudent2:" << endl;
    student2.display();

    cout << "\nstudent3:" << endl;
    student3.display();

    return 0;
}

🔒 访问控制

1. 访问修饰符

C++
// 访问修饰符
#include <iostream>
using namespace std;

class AccessExample {
private:
    int privateVar;

protected:
    int protectedVar;

public:
    int publicVar;

    AccessExample() {
        privateVar = 1;
        protectedVar = 2;
        publicVar = 3;
    }

    void display() {
        cout << "privateVar: " << privateVar << endl;
        cout << "protectedVar: " << protectedVar << endl;
        cout << "publicVar: " << publicVar << endl;
    }

    int getPrivateVar() const {
        return privateVar;
    }

    int getProtectedVar() const {
        return protectedVar;
    }
};

class DerivedClass : public AccessExample {
public:
    void accessMembers() {
        // 可以访问protected和public成员
        cout << "protectedVar: " << protectedVar << endl;
        cout << "publicVar: " << publicVar << endl;

        // 不能访问private成员
        // cout << privateVar << endl;  // 错误!
    }
};

int main() {
    AccessExample obj;
    obj.display();

    // 只能访问public成员
    cout << "publicVar: " << obj.publicVar << endl;
    // cout << obj.privateVar << endl;  // 错误!

    DerivedClass derived;
    derived.accessMembers();

    return 0;
}

🧬 继承

1. 继承基础

C++
// 继承基础
#include <iostream>
#include <string>
using namespace std;

class Animal {
protected:
    string name;

public:
    Animal(string n) : name(n) {}

    void eat() {
        cout << name << "在吃东西" << endl;
    }

    void sleep() {
        cout << name << "在睡觉" << endl;
    }

    virtual void makeSound() {  // virtual 声明虚函数,启用运行时多态
        cout << name << "发出声音" << endl;
    }
};

class Dog : public Animal {
private:
    string breed;

public:
    Dog(string n, string b) : Animal(n), breed(b) {}

    void makeSound() override {  // override 显式标记重写虚函数
        cout << name << "汪汪叫" << endl;
    }

    void fetch() {
        cout << name << "去捡球" << endl;
    }

    string getBreed() const {
        return breed;
    }
};

int main() {
    Dog dog("旺财", "金毛");

    // 调用父类方法
    dog.eat();
    dog.sleep();

    // 调用重写的方法
    dog.makeSound();

    // 调用子类特有方法
    dog.fetch();
    cout << "品种: " << dog.getBreed() << endl;

    return 0;
}

🎭 多态

1. 虚函数

C++
// 虚函数
#include <iostream>
#include <vector>
using namespace std;

class Shape {
public:
    virtual void draw() {
        cout << "绘制形状" << endl;
    }

    virtual double getArea() {
        return 0;
    }

    virtual ~Shape() {
        cout << "形状对象被销毁" << endl;
    }
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : radius(r) {}

    void draw() override {
        cout << "绘制圆形" << endl;
    }

    double getArea() override {
        return 3.141592653589793 * radius * radius;
    }

    ~Circle() {
        cout << "圆形对象被销毁" << endl;
    }
};

class Rectangle : public Shape {
private:
    double width;
    double height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}

    void draw() override {
        cout << "绘制矩形" << endl;
    }

    double getArea() override {
        return width * height;
    }

    ~Rectangle() {
        cout << "矩形对象被销毁" << endl;
    }
};

int main() {
    // 使用多态(教学示例,生产代码应使用 unique_ptr,见本文“内存管理”专节)
    vector<Shape*> shapes;
    shapes.push_back(new Circle(5.0));
    shapes.push_back(new Rectangle(4.0, 6.0));
    shapes.push_back(new Circle(3.0));

    cout << "遍历形状:" << endl;
    for (const Shape* shape : shapes) {
        shape->draw();
        cout << "面积: " << shape->getArea() << endl;
    }

    // 释放内存
    for (Shape* shape : shapes) {
        delete shape;
    }

    return 0;
}

💡 最佳实践

1. 类设计

C++
// 类设计
int main() {
    // ✅ 好的设计:使用封装
    class GoodClass {
    private:
        int value;
    public:
        void setValue(int v) { value = v; }
        int getValue() const { return value; }
    };

    // ❌ 不好的设计:公开成员变量
    class BadClass {
    public:
        int value;
    };

    return 0;
}

2. 内存管理

C++
// 内存管理
#include <memory>

int main() {
    // ✅ 好的做法:使用智能指针
    std::unique_ptr<int> ptr = std::make_unique<int>(10);

    // ❌ 不好的做法:手动管理内存
    int* rawPtr = new int(10);
    // delete rawPtr;  // 容易忘记

    return 0;
}

📝 练习题

基础题

  1. 如何定义类和对象?
  2. 构造函数有哪些类型?
  3. 什么是继承和多态?

进阶题

  1. 实现一个合理的类层次结构。
  2. 使用虚函数实现多态。
  3. 设计一个合理的访问控制方案。

实践题

  1. 创建一个学生管理系统。
  2. 实现一个简单的图形计算器。
  3. 构建一个游戏角色系统。

📚 推荐阅读

🔗 下一章

数组与链表 - 学习C++的数组和链表。