一、基础概念
- 什么是类?
定义:类是用户自定义的数据类型,是对象的蓝图或模板。
组成:
成员变量(属性):描述对象的特征(如:汽车的品牌、颜色)
成员函数(方法):定义对象的行为(如:汽车启动、加速)
- 什么是对象?
定义:对象是类的实例(Instance),占用内存空间。
类比:
类 → 建筑设计图纸
对象 → 按图纸建造的房子
二、类的定义与使用
- 基本语法
class ClassName {
public: // 访问修饰符(后续详解)// 成员变量DataType member1;DataType member2;// 成员函数ReturnType method1(Parameters) { ... }ReturnType method2(Parameters);
};// 类外定义成员函数
ReturnType ClassName::method2(Parameters) { ... }
- 示例:汽车类
#include <iostream>
#include <string>class Car {
public:// 成员变量std::string brand;std::string color;int speed;// 成员函数void accelerate(int increment) {speed += increment;}void displayInfo() {std::cout << brand << " " << color << ", Speed: " << speed << " km/h\n";}
};int main() {// 创建对象Car myCar;myCar.brand = "Toyota";myCar.color = "Red";myCar.speed = 0;// 调用方法myCar.accelerate(20);myCar.displayInfo(); // 输出: Toyota Red, Speed: 20 km/hreturn 0;
}
三、访问控制
- 访问修饰符
- public:类外可直接访问
- private(默认):仅类内和友元可访问
- protected:类内、派生类、友元可访问
- 封装(Encapsulation)原则
隐藏内部实现,通过公共接口控制访问
- 目的:规范访问
- 示例:
class BankAccount {
private:double balance; // 私有变量public:void deposit(double amount) {if (amount > 0) balance += amount;}double getBalance() {return balance;}
};int main() {BankAccount account;account.deposit(1000);// account.balance = -500; // 错误!无法直接访问私有成员std::cout << account.getBalance(); // 正确
}
四、构造函数(Constructor)与析构函数(Destructor)
- 构造函数
- 作用:初始化对象(自动调用)
- 特点:
与类同名
无返回类型
可重载(多个构造函数) - 示例:
class Student {
private:std::string name;int age;public:// 默认构造函数Student() : name("Unknown"), age(0) {}// 带参数构造函数Student(std::string n, int a) : name(n), age(a) {}void display() {std::cout << name << ", " << age << " years old\n";}
};int main() {Student s1; // 调用默认构造函数Student s2("Alice", 20); // 调用带参数构造函数s2.display(); // Alice, 20 years old
}
- 析构函数
- 作用:清理资源(如释放内存)
- 特点:
名称:~ClassName()
无参数,不可重载 - 示例:
class FileHandler {
public:FileHandler() { std::cout << "File opened\n"; }~FileHandler() { std::cout << "File closed\n"; } // 析构函数
};int main() {FileHandler f; // 构造时输出// 析构函数在对象离开作用域时自动调用
}
// 输出:
// File opened
// File closed
五、静态成员
- 静态变量
- 特性:
属于类而非对象
所有对象共享同一份拷贝 - 示例:
class Counter {
public:static int count; // 声明静态变量Counter() { count++; }~Counter() { count--; }
};int Counter::count = 0; // 定义并初始化int main() {Counter c1, c2;//定义c1和c2时都进行了加一操作std::cout << Counter::count; // 输出 2
}
- 静态函数
- 只能访问静态成员
- 示例:
class MathUtils {
public:static int square(int x) { return x * x; }
};int main() {std::cout << MathUtils::square(5); // 输出 25
}
六、继承(Inheritance)
- 基本语法
class BaseClass { /* ... */ };// 公有继承
class DerivedClass : public BaseClass { /* ... */ };
- 示例:动物类层次
class Animal {
public:void eat() { std::cout << "Eating...\n"; }
};class Dog : public Animal {
public:void bark() { std::cout << "Woof!\n"; }
};int main() {Dog myDog;myDog.eat(); // 继承自基类myDog.bark(); // 派生类自有方法
}
七、多态(Polymorphism)
- 虚函数(Virtual Functions)
class Shape {
public:virtual void draw() { // 虚函数std::cout << "Drawing a shape\n";}
};class Circle : public Shape {
public:void draw() override { // 重写虚函数std::cout << "Drawing a circle\n";}
};int main() {Shape* shape = new Circle();shape->draw(); // 输出: Drawing a circledelete shape;
}
八、练习与巩固
基础练习:
定义一个 Book 类,包含书名、作者、价格属性和显示信息的方法。
- 简单版本代码示例:
#include <iostream>
#include <string>class Book {
public:// 成员变量std::string book_name;std::string author;float price;// 成员函数void displayInfo() {std::cout << book_name << " " << author << ", price: " << price << "yuan\n";}
};int main() {// 创建对象Book mybook;mybook.book_name = "if give me three days light";mybook.author = "omb";mybook.price = 20.5;// 调用方法mybook.displayInfo(); // 输出: Toyota Red, Speed: 20 km/hreturn 0;
}
- 改进版:
代码评价与改进建议
- 封装性不足
问题:成员变量(book_name, author, price)被声明为 public,外部可以直接修改,破坏了面向对象的封装原则。
改进:将成员变量设为 private,通过公共方法(getter/setter)访问。
- 缺少构造函数
问题:对象创建后需要逐个手动赋值,容易遗漏初始化。
改进:添加构造函数,方便对象初始化。
- 代码规范性
建议:避免 using namespace std;,改为显式使用 std:: 前缀(防止命名冲突)。
改进后的代码:
#include <iostream>
#include <string>class Book {
private: // 成员变量设为私有,增强封装性std::string book_name;std::string author;double price; // 使用 double 提高精度public:// 构造函数(初始化成员变量)Book(const std::string& name, const std::string& author_name, double book_price): book_name(name), author(author_name), price(book_price) {}// 显示书籍信息(const 表示不修改成员变量)void displayInfo() const {std::cout << "Book: " << book_name << "\nAuthor: " << author << "\nPrice: " << price << " yuan\n";}// Getter/Setter 方法(保护数据安全)void setPrice(double new_price) {if (new_price >= 0) { // 简单的数据校验price = new_price;}}double getPrice() const { return price; }// 可以类似添加其他属性的 getter/setter
};int main() {// 使用构造函数初始化对象Book mybook("If I Had Three Days of Light", "Helen Keller", 20.5);// 调用方法显示信息mybook.displayInfo(); // 输出正确的书籍信息// 修改价格(通过 setter)mybook.setPrice(25.0);std::cout << "Updated price: " << mybook.getPrice() << " yuan\n";return 0;
}
改进点详解
- 封装性
为什么重要:封装是面向对象的核心原则,可以防止外部代码意外修改对象内部状态。
实现方式:
成员变量设为 private
通过 getPrice() 和 setPrice() 方法访问和修改价格
- 构造函数
优势:
- 强制在创建对象时提供完整初始化数据
- 避免对象处于“半初始化”状态
- 使用成员初始化列表(更高效)
语法:
Book(const std::string& name, const std::string& author_name, double book_price): book_name(name), author(author_name), price(book_price) {}
- 输出格式修正
修正后的输出示例:
Book: If I Had Three Days of LightAuthor: Helen KellerPrice: 20.5 yuan
- 其他优化
数据类型:price 改为 double(更精确的浮点数)
const 正确性:displayInfo() 和 getPrice() 标记为 const
数据校验:在 setPrice() 中检查价格非负
进阶挑战:
- 实现一个 Stack 类,包含压栈(push)、弹栈(pop)、查看栈顶元素的方法
- 使用私有数组存储数据,确保封装性