Appearance
C++ 数据封装
数据封装是指将数据和操作数据的方法绑定在一起,并隐藏对象的内部实现细节。它是面向对象编程的核心概念之一,通过类来实现。
1. 数据封装的基本概念
数据封装依赖于三个关键概念:
- 数据成员:存储对象的状态
- 成员函数:操作数据成员的方法
- 访问修饰符:控制对数据成员和成员函数的访问权限
1.1 示例
cpp
#include <iostream>
class Student {
private:
std::string name;
int age;
float gpa;
public:
Student(std::string name, int age, float gpa)
: name(name), age(age), gpa(gpa) {}
void set_name(std::string name) {
this->name = name;
}
std::string get_name() {
return name;
}
void set_age(int age) {
this->age = age;
}
int get_age() {
return age;
}
void set_gpa(float gpa) {
if (gpa >= 0.0f && gpa <= 4.0f) {
this->gpa = gpa;
}
}
float get_gpa() {
return gpa;
}
void display() {
std::cout << "姓名: " << name << std::endl;
std::cout << "年龄: " << age << std::endl;
std::cout << "GPA: " << gpa << std::endl;
}
};
int main() {
Student student("张三", 20, 3.8f);
student.display();
student.set_name("李四");
student.set_age(21);
student.set_gpa(3.9f);
student.display();
return 0;
}2. 访问修饰符
访问修饰符是实现数据封装的重要工具。
2.1 private 成员
private成员只能在类内部被访问,外部无法直接访问。
cpp
#include <iostream>
class BankAccount {
private:
double balance;
public:
BankAccount(double initial_balance) : balance(initial_balance) {}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
}
}
double get_balance() {
return balance;
}
};
int main() {
BankAccount account(1000.0);
account.deposit(500.0);
account.withdraw(200.0);
std::cout << "余额: " << account.get_balance() << std::endl;
return 0;
}2.2 public 成员
public成员可以在任何地方被访问。
cpp
#include <iostream>
class Point {
public:
int x;
int y;
Point(int x, int y) : x(x), y(y) {}
void print() {
std::cout << "(" << x << ", " << y << ")" << std::endl;
}
};
int main() {
Point point(10, 20);
point.x = 30;
point.y = 40;
point.print();
return 0;
}2.3 protected 成员
protected成员可以在类内部和派生类中被访问。
cpp
#include <iostream>
class Base {
protected:
int x;
public:
Base(int x) : x(x) {}
void set_x(int x) {
this->x = x;
}
int get_x() {
return x;
}
};
class Derived : public Base {
public:
Derived(int x) : Base(x) {}
void increment_x() {
x++;
}
};
int main() {
Derived derived(10);
derived.increment_x();
std::cout << "x = " << derived.get_x() << std::endl;
return 0;
}3. Getter 和 Setter 方法
Getter 和 Setter 方法是访问和修改私有成员的标准方式。
3.1 基本用法
cpp
#include <iostream>
class Person {
private:
std::string name;
int age;
public:
Person(std::string name, int age) : name(name), age(age) {}
void set_name(std::string name) {
this->name = name;
}
std::string get_name() {
return name;
}
void set_age(int age) {
if (age >= 0) {
this->age = age;
}
}
int get_age() {
return age;
}
};
int main() {
Person person("张三", 20);
std::cout << "姓名: " << person.get_name() << std::endl;
std::cout << "年龄: " << person.get_age() << std::endl;
person.set_name("李四");
person.set_age(21);
std::cout << "姓名: " << person.get_name() << std::endl;
std::cout << "年龄: " << person.get_age() << std::endl;
return 0;
}4. 数据封装的好处
4.1 保护数据
cpp
#include <iostream>
class BankAccount {
private:
double balance;
public:
BankAccount(double initial_balance) : balance(initial_balance) {}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
}
}
double get_balance() {
return balance;
}
};
int main() {
BankAccount account(1000.0);
account.deposit(500.0);
account.withdraw(200.0);
account.deposit(-100.0); // 无效操作
account.withdraw(2000.0); // 无效操作
std::cout << "余额: " << account.get_balance() << std::endl;
return 0;
}4.2 提高代码的可维护性
cpp
#include <iostream>
class Temperature {
private:
double celsius;
public:
Temperature(double celsius) : celsius(celsius) {}
void set_celsius(double celsius) {
this->celsius = celsius;
}
double get_celsius() {
return celsius;
}
void set_fahrenheit(double fahrenheit) {
celsius = (fahrenheit - 32) * 5.0 / 9.0;
}
double get_fahrenheit() {
return celsius * 9.0 / 5.0 + 32;
}
void set_kelvin(double kelvin) {
celsius = kelvin - 273.15;
}
double get_kelvin() {
return celsius + 273.15;
}
};
int main() {
Temperature temp(25.0);
std::cout << "摄氏度: " << temp.get_celsius() << std::endl;
std::cout << "华氏度: " << temp.get_fahrenheit() << std::endl;
std::cout << "开尔文: " << temp.get_kelvin() << std::endl;
std::cout << std::endl;
temp.set_fahrenheit(77.0);
std::cout << "摄氏度: " << temp.get_celsius() << std::endl;
std::cout << "华氏度: " << temp.get_fahrenheit() << std::endl;
std::cout << "开尔文: " << temp.get_kelvin() << std::endl;
return 0;
}5. 示例:综合运用
现在,让我们看一个综合运用数据封装特性的例子:
cpp
#include <iostream>
#include <string>
class Book {
private:
std::string title;
std::string author;
double price;
int quantity;
public:
Book(std::string title, std::string author, double price, int quantity)
: title(title), author(author), price(price), quantity(quantity) {}
void set_title(std::string title) {
this->title = title;
}
std::string get_title() {
return title;
}
void set_author(std::string author) {
this->author = author;
}
std::string get_author() {
return author;
}
void set_price(double price) {
if (price > 0) {
this->price = price;
}
}
double get_price() {
return price;
}
void set_quantity(int quantity) {
if (quantity >= 0) {
this->quantity = quantity;
}
}
int get_quantity() {
return quantity;
}
void add_quantity(int amount) {
if (amount > 0) {
quantity += amount;
}
}
void sell_quantity(int amount) {
if (amount > 0 && amount <= quantity) {
quantity -= amount;
}
}
double get_total_value() {
return price * quantity;
}
void display() {
std::cout << "书名: " << title << std::endl;
std::cout << "作者: " << author << std::endl;
std::cout << "价格: " << price << std::endl;
std::cout << "数量: " << quantity << std::endl;
std::cout << "总价值: " << get_total_value() << std::endl;
}
};
int main() {
Book book("C++ Primer", "Stanley B. Lippman", 89.0, 10);
std::cout << "书籍信息:" << std::endl;
book.display();
std::cout << std::endl;
book.add_quantity(5);
std::cout << "添加 5 本后:" << std::endl;
book.display();
std::cout << std::endl;
book.sell_quantity(3);
std::cout << "卖出 3 本后:" << std::endl;
book.display();
std::cout << std::endl;
book.set_price(99.0);
std::cout << "更新价格后:" << std::endl;
book.display();
return 0;
}小结
C++ 数据封装包括:
数据封装的基本概念:
- 数据成员:存储对象的状态
- 成员函数:操作数据成员的方法
- 访问修饰符:控制对数据成员和成员函数的访问权限
访问修饰符:
private成员:只能在类内部被访问public成员:可以在任何地方被访问protected成员:可以在类内部和派生类中被访问
Getter 和 Setter 方法:
- Getter 方法:获取私有成员的值
- Setter 方法:设置私有成员的值
数据封装的好处:
- 保护数据:防止外部直接修改私有成员
- 提高代码的可维护性:可以修改实现而不影响外部代码
- 降低代码的耦合度:通过接口访问数据
关键概念:
- 数据封装:将数据和操作数据的方法绑定在一起,并隐藏对象的内部实现细节
- 数据成员:存储对象的状态
- 成员函数:操作数据成员的方法
- 访问修饰符:控制对数据成员和成员函数的访问权限
- Getter 方法:获取私有成员的值
- Setter 方法:设置私有成员的值
掌握数据封装是 C++ 面向对象编程的重要基础,在后续章节中,我们将学习 C++ 的接口(抽象类)。