首页 > 应用开发 > IT综合 > 从面向过程到面向对象:类封装与this指针深度解析
# 从面向过程到面向对象:类封装与this指针深度解析
## 编程范式的演变:从过程到对象
面向过程编程关注数据结构和算法分离,而面向对象编程将数据和操作数据的方法绑定在一起。这种思维方式的转变是现代软件开发的里程碑。
### 面向过程编程示例
```c
// 面向过程的学生成绩管理
#include <stdio.h>
#include <string.h>
#define MAX_STUDENTS 100
// 数据结构定义
struct Student {
char name[50];
int id;
float grades[5];
};
// 操作数据的函数
void initialize_student(struct Student* s, const char* name, int id) {
strcpy(s->name, name);
s->id = id;
for (int i = 0; i < 5; i++) {
s->grades[i] = 0.0f;
}
}
void set_grade(struct Student* s, int course_index, float grade) {
if (course_index >= 0 && course_index < 5) {
s->grades[course_index] = grade;
}
}
float calculate_average(struct Student* s) {
float sum = 0.0f;
for (int i = 0; i < 5; i++) {
sum += s->grades[i];
}
return sum / 5.0f;
}
void print_student_info(struct Student* s) {
printf("学生ID: %d\n", s->id);
printf("姓名: %s\n", s->name);
printf("成绩: ");
for (int i = 0; i < 5; i++) {
printf("%.1f ", s->grades[i]);
}
printf("\n平均分: %.2f\n", calculate_average(s));
}
// 使用面向过程的方式
void procedural_demo() {
struct Student students[MAX_STUDENTS];
int student_count = 0;
// 添加学生
initialize_student(&students[0], "张三", 1001);
set_grade(&students[0], 0, 85.5);
set_grade(&students[0], 1, 90.0);
set_grade(&students[0], 2, 78.5);
// 处理学生数据
print_student_info(&students[0]);
}
```
### 面向对象编程示例
```cpp
// 面向对象的学生类
class Student {
private:
std::string name;
int id;
float grades[5];
int grade_count;
public:
// 构造函数
Student(const std::string& student_name, int student_id)
: name(student_name), id(student_id), grade_count(0) {
for (int i = 0; i < 5; i++) {
grades[i] = 0.0f;
}
}
// 成员函数:操作对象内部数据
void setGrade(int course_index, float grade) {
if (course_index >= 0 && course_index < 5) {
grades[course_index] = grade;
if (grade != 0.0f && course_index >= grade_count) {
grade_count = course_index + 1;
}
}
}
float calculateAverage() const {
if (grade_count == 0) return 0.0f;
float sum = 0.0f;
for (int i = 0; i < grade_count; i++) {
sum += grades[i];
}
return sum / grade_count;
}
void displayInfo() const {
std::cout << "学生ID: " << id << std::endl;
std::cout << "姓名: " << name << std::endl;
std::cout << "成绩: ";
for (int i = 0; i < grade_count; i++) {
std::cout << grades[i] << " ";
}
std::cout << "\n平均分: " << calculateAverage() << std::endl;
}
// 访问器函数
std::string getName() const { return name; }
int getId() const { return id; }
// 修改器函数
void setName(const std::string& new_name) { name = new_name; }
};
// 使用面向对象的方式
void object_oriented_demo() {
// 创建学生对象
Student student1("张三", 1001);
// 通过对象调用方法
student1.setGrade(0, 85.5);
student1.setGrade(1, 90.0);
student1.setGrade(2, 78.5);
// 对象自动管理自己的状态
student1.displayInfo();
// 多个对象实例
Student student2("李四", 1002);
student2.setGrade(0, 92.0);
student2.setGrade(1, 88.5);
// 每个对象有独立的状态
std::cout << "\n学生1平均分: " << student1.calculateAverage() << std::endl;
std::cout << "学生2平均分: " << student2.calculateAverage() << std::endl;
}
```
## 类的定义:数据与行为的封装
### 类的基本结构
```cpp
// 银行账户类的完整定义
class BankAccount {
private:
// 私有数据成员:封装实现细节
std::string account_number;
std::string account_holder;
double balance;
static int total_accounts; // 静态成员:所有对象共享
public:
// 静态成员函数
static int getTotalAccounts() {
return total_accounts;
}
// 构造函数
BankAccount(const std::string& number, const std::string& holder, double initial_balance = 0.0)
: account_number(number), account_holder(holder), balance(initial_balance) {
total_accounts++; // 创建新账户时增加计数
std::cout << "账户创建: " << account_number << std::endl;
}
// 析构函数
~BankAccount() {
total_accounts--; // 账户销毁时减少计数
std::cout << "账户销毁: " << account_number << std::endl;
}
// 存款方法
void deposit(double amount) {
if (amount > 0) {
balance += amount;
std::cout << "存款 " << amount << " 成功" << std::endl;
}
}
// 取款方法(返回是否成功)
bool withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
std::cout << "取款 " << amount << " 成功" << std::endl;
return true;
}
std::cout << "取款失败: 余额不足或金额无效" << std::endl;
return false;
}
// 查询余额
double getBalance() const {
return balance;
}
// 显示账户信息
void displayInfo() const {
std::cout << "账户号码: " << account_number << std::endl;
std::cout << "账户持有人: " << account_holder << std::endl;
std::cout << "账户余额: " << balance << std::endl;
}
// 转账功能
bool transferTo(BankAccount& target_account, double amount) {
if (withdraw(amount)) {
target_account.deposit(amount);
std::cout << "转账 " << amount << " 到账户 "
<< target_account.account_number << " 成功" << std::endl;
return true;
}
return false;
}
};
// 静态成员初始化
int BankAccount::total_accounts = 0;
void bank_account_demo() {
std::cout << "=== 银行账户系统演示 ===" << std::endl;
// 创建账户
BankAccount account1("001", "张三", 1000.0);
BankAccount account2("002", "李四", 500.0);
std::cout << "当前总账户数: " << BankAccount::getTotalAccounts() << std::endl;
// 操作账户
account1.deposit(500.0);
account1.withdraw(200.0);
// 转账
account1.transferTo(account2, 300.0);
// 显示账户信息
std::cout << "\n账户1信息:" << std::endl;
account1.displayInfo();
std::cout << "\n账户2信息:" << std::endl;
account2.displayInfo();
// 静态成员访问
std::cout << "\n最终总账户数: " << BankAccount::getTotalAccounts() << std::endl;
}
```
## 封装:数据保护与接口设计
### 访问控制与数据隐藏
```cpp
// 封装示例:温度控制器
class TemperatureController {
private:
// 私有数据:外部不能直接访问
double current_temperature;
double target_temperature;
bool is_heating;
bool is_cooling;
// 私有方法:实现细节隐藏
void activateHeater() {
is_heating = true;
is_cooling = false;
std::cout << "加热器启动" << std::endl;
}
void activateCooler() {
is_cooling = true;
is_heating = false;
std::cout << "制冷器启动" << std::endl;
}
void deactivateAll() {
is_heating = is_cooling = false;
std::cout << "所有设备关闭" << std::endl;
}
public:
// 构造函数
TemperatureController()
: current_temperature(20.0), target_temperature(22.0),
is_heating(false), is_cooling(false) {}
// 公共接口:设置目标温度
void setTargetTemperature(double target) {
if (target >= 10.0 && target <= 35.0) {
target_temperature = target;
std::cout << "目标温度设置为: " << target << "°C" << std::endl;
adjustTemperature();
} else {
std::cout << "错误:目标温度超出范围(10-35°C)" << std::endl;
}
}
// 更新当前温度(模拟传感器读数)
void updateCurrentTemperature(double current) {
current_temperature = current;
std::cout << "当前温度更新为: " << current << "°C" << std::endl;
adjustTemperature();
}
// 获取状态信息
double getCurrentTemperature() const { return current_temperature; }
double getTargetTemperature() const { return target_temperature; }
bool isHeating() const { return is_heating; }
bool isCooling() const { return is_cooling; }
// 显示状态
void displayStatus() const {
std::cout << "\n=== 温度控制器状态 ===" << std::endl;
std::cout << "当前温度: " << current_temperature << "°C" << std::endl;
std::cout << "目标温度: " << target_temperature << "°C" << std::endl;
std::cout << "加热器: " << (is_heating ? "运行中" : "停止") << std::endl;
std::cout << "制冷器: " << (is_cooling ? "运行中" : "停止") << std::endl;
std::cout << "========================\n" << std::endl;
}
private:
// 内部温度调节逻辑
void adjustTemperature() {
double difference = target_temperature - current_temperature;
if (std::abs(difference) < 0.5) {
// 温度接近目标,关闭所有设备
deactivateAll();
} else if (difference > 0) {
// 需要加热
activateHeater();
} else {
// 需要制冷
activateCooler();
}
}
};
void encapsulation_demo() {
std::cout << "=== 温度控制器封装演示 ===" << std::endl;
TemperatureController controller;
// 只能通过公共接口操作对象
controller.setTargetTemperature(25.0);
controller.displayStatus();
// 模拟温度变化
controller.updateCurrentTemperature(20.0);
controller.displayStatus();
controller.updateCurrentTemperature(26.0);
controller.displayStatus();
controller.updateCurrentTemperature(24.8);
controller.displayStatus();
// 尝试非法操作
controller.setTargetTemperature(40.0); // 超出范围,会被拒绝
// 获取状态(只读访问)
std::cout << "当前温度: " << controller.getCurrentTemperature() << "°C" << std::endl;
// 无法直接访问私有成员
// controller.current_temperature = 100.0; // 编译错误
// controller.activateHeater(); // 编译错误
}
```
## this指针:对象自我引用机制
### this指针的基本概念
```cpp
// this指针演示类
class Product {
private:
int id;
std::string name;
double price;
int stock;
public:
// 构造函数
Product(int product_id, const std::string& product_name, double product_price, int product_stock = 0)
: id(product_id), name(product_name), price(product_price), stock(product_stock) {}
// 使用this指针区分类成员和参数
void setId(int id) {
this->id = id; // this->id 表示成员变量,id 表示参数
<"movie.q6k0.org.cn"><"kazb.q6k0.org.cn"><"af.q6k0.org.cn">
}
void setName(const std::string& name) {
this->name = name;
}
// 返回对象自身的引用(支持链式调用)
Product& setPrice(double price) {
this->price = price;
return *this; // 返回当前对象的引用
}
Product& setStock(int stock) {
this->stock = stock;
return *this;
}
// 比较函数:使用this指针访问当前对象
bool isMoreExpensiveThan(const Product& other) const {
return this->price > other.price;
}
// 静态函数没有this指针
static double calculateDiscount(double price, double discount_rate) {
// 不能访问非静态成员
// this->price = 100; // 错误:静态函数没有this指针
return price * (1 - discount_rate);
}
// 显示产品信息
void display() const {
std::cout << "产品ID: " << this->id << std::endl;
std::cout << "产品名称: " << this->name << std::endl;
std::cout << "价格: " << this->price << std::endl;
std::cout << "库存: " << this->stock << std::endl;
}
// 返回对象自身的指针(不常见但可能有用)
Product* getThisPointer() {
return this;
}
// 返回对象自身的常量指针
const Product* getConstThisPointer() const {
return this;
}
};
void this_pointer_demo() {
std::cout << "=== this指针演示 ===" << std::endl;
Product laptop(101, "笔记本电脑", 5999.0, 10);
Product phone(102, "智能手机", 2999.0, 20);
// 链式调用:每个修改函数都返回*this
laptop.setPrice(5499.0)
.setStock(8)
.display();
// 比较产品价格
if (laptop.isMoreExpensiveThan(phone)) {
std::cout << "笔记本电脑比手机贵" << std::endl;
}
// 使用this指针解决命名冲突
laptop.setId(103);
laptop.setName("高端笔记本电脑");
// 获取this指针
Product* laptop_ptr = laptop.getThisPointer();
laptop_ptr->setPrice(6999.0);
// 静态函数调用
double discounted_price = Product::calculateDiscount(6999.0, 0.1);
std::cout << "折扣后价格: " << discounted_price << std::endl;
}
```
### this指针的高级应用
```cpp
// 使用this实现自引用数据结构
class TreeNode {
private:
int value;
TreeNode* left;
TreeNode* right;
TreeNode* parent; // 指向父节点的指针
public:
TreeNode(int val, TreeNode* parent_node = nullptr)
: value(val), left(nullptr), right(nullptr), parent(parent_node) {}
// 插入节点:返回插入的节点指针
TreeNode* insert(int new_value) {
if (new_value < value) {
if (left == nullptr) {
left = new TreeNode(new_value, this); // this作为父节点
return left;
} else {
return left->insert(new_value);
}
} else {
if (right == nullptr) {
right = new TreeNode(new_value, this); // this作为父节点
return right;
} else {
return right->insert(new_value);
}
}
}
// 获取兄弟节点
TreeNode* getSibling() const {
if (parent == nullptr) return nullptr;
if (parent->left == this) {
return parent->right;
} else {
return parent->left;
}
}
// 获取根节点
TreeNode* getRoot() {
TreeNode* current = this;
while (current->parent != nullptr) {
current = current->parent;
}
return current;
}
// 显示树结构
void display(int depth = 0) const {
// 显示右子树
if (right != nullptr) {
right->display(depth + 1);
}
// 显示当前节点
for (int i = 0; i < depth; i++) {
std::cout << " ";
}
std::cout << value;
if (parent != nullptr) {
std::cout << " (父: " << parent->value << ")";
}
std::cout << std::endl;
// 显示左子树
if (left != nullptr) {
left->display(depth + 1);
}
}
~TreeNode() {
delete left;
delete right;
}
};
void tree_structure_demo() {
std::cout << "=== 自引用树结构演示 ===" << std::endl;
// 创建二叉搜索树
TreeNode* root = new TreeNode(50);
// 插入节点
root->insert(30);
root->insert(70);
root->insert(20);
root->insert(40);
root->insert(60);
root->insert(80);
// 显示树结构
std::cout << "树结构(右侧在上方):" << std::endl;
root->display();
// 访问节点
TreeNode* node_40 = root->insert(35);
if (node_40) {
std::cout << "\n节点35的兄弟节点: ";
TreeNode* sibling = node_40->getSibling();
if (sibling) {
std::cout << sibling->value << std::endl;
}
std::cout << "节点35的根节点: " << node_40->getRoot()->value << std::endl;
}
delete root;
}
```
## 从过程到对象的思维转换
### 案例:图形计算系统的重构
```c
// 面向过程的图形计算(重构前)
#include <math.h>
struct Circle {
double x, y; // 圆心坐标
double radius;
};
struct Rectangle {
double x, y; // 左上角坐标
double width, height;
};
// 全局函数操作图形
double circle_area(struct Circle* c) {
return M_PI * c->radius * c->radius;
}
double rectangle_area(struct Rectangle* r) {
return r->width * r->height;
}
int circle_contains_point(struct Circle* c, double px, double py) {
double dx = px - c->x;
double dy = py - c->y;
return (dx*dx + dy*dy) <= (c->radius * c->radius);
}
int rectangle_contains_point(struct Rectangle* r, double px, double py) {
return (px >= r->x && px <= r->x + r->width &&
py >= r->y && py <= r->y + r->height);
}
void process_shapes() {
struct Circle c = {0, 0, 5};
struct Rectangle r = {0, 0, 10, 5};
printf("圆面积: %.2f\n", circle_area(&c));
printf("矩形面积: %.2f\n", rectangle_area(&r));
if (circle_contains_point(&c, 3, 4)) {
printf("点(3,4)在圆内\n");
}
}
```
```cpp
// 面向对象的图形系统(重构后)
#include <cmath>
#include <vector>
#include <memory>
// 抽象基类:定义图形接口
class Shape {
public:
virtual ~Shape() = default;
// 纯虚函数:子类必须实现
virtual double area() const = 0;
virtual double perimeter() const = 0;
virtual bool containsPoint(double x, double y) const = 0;
virtual void display() const = 0;
// 非虚函数:通用功能
void move(double dx, double dy) {
translate(dx, dy);
}
protected:
// 受保护的虚函数:子类可重写
virtual void translate(double dx, double dy) = 0;
};
// 具体图形类:圆形
class Circle : public Shape {
private:
double center_x, center_y;
double radius;
public:
Circle(double x, double y, double r)
: center_x(x), center_y(y), radius(r) {
if (radius <= 0) {
throw std::invalid_argument("半径必须为正数");
}
}
double area() const override {
return M_PI * radius * radius;
}
double perimeter() const override {
return 2 * M_PI * radius;
}
bool containsPoint(double x, double y) const override {
double dx = x - center_x;
double dy = y - center_y;
return (dx*dx + dy*dy) <= (radius * radius);
}
void display() const override {
std::cout << "圆形 - 圆心(" << center_x << ", " << center_y
<< "), 半径: " << radius
<< ", 面积: " << area() << std::endl;
}
// 圆形特有方法
double getDiameter() const {
return 2 * radius;
}
protected:
void translate(double dx, double dy) override {
center_x += dx;
center_y += dy;
}
};
// 具体图形类:矩形
class Rectangle : public Shape {
private:
double x, y; // 左上角坐标
double width, height;
public:
Rectangle(double x_pos, double y_pos, double w, double h)
: x(x_pos), y(y_pos), width(w), height(h) {
if (width <= 0 || height <= 0) {
throw std::invalid_argument("宽度和高度必须为正数");
}
}
double area() const override {
return width * height;
}
double perimeter() const override {
return 2 * (width + height);
}
bool containsPoint(double px, double py) const override {
return (px >= x && px <= x + width &&
py >= y && py <= y + height);
}
void display() const override {
std::cout << "矩形 - 位置(" << x << ", " << y
<< "), 尺寸: " << width << "x" << height
<< ", 面积: " << area() << std::endl;
}
// 矩形特有方法
double getDiagonal() const {
return std::sqrt(width*width + height*height);
}
protected:
void translate(double dx, double dy) override {
x += dx;
y += dy;
}
};
// 图形管理器:利用多态管理多种图形
class ShapeManager {
private:
std::vector<std::unique_ptr<Shape>> shapes;
public:
void addShape(std::unique_ptr<Shape> shape) {
shapes.push_back(std::move(shape));
}
double totalArea() const {
double total = 0;
for (const auto& shape : shapes) {
total += shape->area();
}
return total;
}
void displayAll() const {
std::cout << "\n=== 所有图形 ===" << std::endl;
for (const auto& shape : shapes) {
shape->display();
}
std::cout << "总面积: " << totalArea() << std::endl;
}
// 查找包含指定点的图形
std::vector<Shape*> findShapesContainingPoint(double x, double y) const {
std::vector<Shape*> result;
for (const auto& shape : shapes) {
if (shape->containsPoint(x, y)) {
result.push_back(shape.get());
<"live.q6k0.org.cn"><"video.q6k0.org.cn"><"mXf9.q6k0.org.cn">
}
}
return result;
}
// 移动所有图形
void moveAll(double dx, double dy) {
for (auto& shape : shapes) {
shape->move(dx, dy);
}
}
};
void object_oriented_graphics_demo() {
std::cout << "=== 面向对象图形系统演示 ===" << std::endl;
ShapeManager manager;
// 创建不同图形(多态)
manager.addShape(std::make_unique<Circle>(0, 0, 5));
manager.addShape(std::make_unique<Rectangle>(10, 10, 8, 6));
manager.addShape(std::make_unique<Circle>(20, 20, 3));
// 显示所有图形
manager.displayAll();
// 查找包含点的图形
auto containing_shapes = manager.findShapesContainingPoint(2, 2);
std::cout << "\n包含点(2,2)的图形数量: "
<< containing_shapes.size() << std::endl;
// 移动所有图形
std::cout << "\n向右移动5个单位..." << std::endl;
manager.moveAll(5, 0);
// 动态类型转换
auto& first_shape = manager.findShapesContainingPoint(5, 0);
if (!first_shape.empty()) {
if (auto circle = dynamic_cast<Circle*>(first_shape[0])) {
std::cout << "第一个图形是圆形,直径: "
<< circle->getDiameter() << std::endl;
} else if (auto rect = dynamic_cast<Rectangle*>(first_shape[0])) {
std::cout << "第一个图形是矩形,对角线: "
<< rect->getDiagonal() << std::endl;
}
}
}
```
## 封装的优势与实践指南
### 封装带来的好处
```cpp
// 未封装的危险代码
class DangerousBankAccount {
public: // 所有成员都是public,极度危险
std::string account_number;
double balance;
void withdraw(double amount) {
// 没有权限检查
// 没有余额验证
balance -= amount;
}
};
// 正确封装的代码
class SafeBankAccount {
private:
std::string account_number;
double balance;
std::string owner_name;
// 私有验证函数
bool validateTransaction(double amount) const {
return amount > 0 && amount <= balance;
}
void logTransaction(const std::string& type, double amount) const {
// 实际项目中会记录到日志文件
std::cout << "交易记录: " << type << " " << amount
<< " (账户: " << account_number << ")" << std::endl;
}
public:
SafeBankAccount(const std::string& number, const std::string& owner, double initial_balance)
: account_number(number), owner_name(owner), balance(initial_balance) {}
bool withdraw(double amount) {
if (validateTransaction(amount)) {
balance -= amount;
logTransaction("取款", amount);
return true;
}
logTransaction("取款失败", amount);
return false;
}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
logTransaction("存款", amount);
}
}
// 只读访问器
double getBalance() const { return balance; }
std::string getAccountNumber() const { return account_number; }
std::string getOwnerName() const { return owner_name; }
};
void encapsulation_benefits_demo() {
std::cout << "=== 封装优势演示 ===" << std::endl;
// 危险账户:外部可以随意修改
DangerousBankAccount dangerous_account;
dangerous_account.account_number = "12345";
dangerous_account.balance = 1000.0;
// 问题1:可以直接修改余额
dangerous_account.balance = -1000.0; // 余额可以为负!
std::cout << "危险账户余额: " << dangerous_account.balance << std::endl;
// 问题2:没有验证的取款
dangerous_account.withdraw(999999.0); // 可以取走不存在的钱
// 安全账户:通过接口访问
SafeBankAccount safe_account("67890", "张三", 1000.0);
// 只能通过受控的接口操作
safe_account.deposit(500.0);
bool success = safe_account.withdraw(2000.0); // 会被拒绝
std::cout << "取款2000元: " << (success ? "成功" : "失败") << std::endl;
// 可以安全查询信息
std::cout << "安全账户余额: " << safe_account.getBalance() << std::endl;
std::cout << "账户持有人: " << safe_account.getOwnerName() << std::endl;
// 无法直接修改内部状态
// safe_account.balance = 999999.0; // 编译错误
}
```
### 面向对象设计原则
1. **单一职责原则**
```cpp
// 违反单一职责的类
class EmployeeManager {
public:
void calculateSalary() { /* ... */ }
void saveToDatabase() { /* ... */ }
void generateReport() { /* ... */ }
void sendEmail() { /* ... */ }
};
// 符合单一职责的类
class Employee {
double calculateSalary() { /* ... */ }
};
class DatabaseService {
void saveEmployee(const Employee& emp) { /* ... */ }
};
class ReportGenerator {
void generateEmployeeReport(const Employee& emp) { /* ... */ }
};
class EmailService {
void sendEmail(const std::string& to, const std::string& message) { /* ... */ }
};
```
2. **开放-封闭原则**
```cpp
// 可扩展的设计
class PaymentProcessor {
public:
virtual void processPayment(double amount) = 0;
virtual ~PaymentProcessor() = default;
};
class CreditCardProcessor : public PaymentProcessor {
void processPayment(double amount) override { /* 信用卡处理 */ }
};
class PayPalProcessor : public PaymentProcessor {
void processPayment(double amount) override { /* PayPal处理 */ }
};
class BankTransferProcessor : public PaymentProcessor {
void processPayment(double amount) override { /* 银行转账处理 */ }
};
```
从面向过程到面向对象的转变不仅是语法上的变化,更是思维方式的重构。通过类的封装,我们将数据和行为紧密结合,通过this指针实现对象自我引用,构建出更加模块化、可维护和可扩展的软件系统。理解这些核心概念对于掌握现代C++编程至关重要。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3106786/ ,如需转载,请注明出处,否则将追究法律责任。