面向对象三大特性深度解析:封装、继承与多态
思维导图概览
目录
- 封装:数据与行为的统一
- 继承:代码复用的艺术
- 继承类型与访问控制
- 构造与析构顺序
- 菱形继承解决方案
- 多态:同一接口的多种实现
- 静态多态(重载与运算符重载)
- 动态多态(虚函数与抽象类)
- 友元机制:打破封装边界
- 综合应用实例
1. 封装:数据与行为的统一
封装是将数据(成员变量)和操作数据的方法(成员函数)捆绑在一起的机制,通过访问控制实现数据隐藏。
class BankAccount {
private: // 封装敏感数据string accountNumber;double balance;public: // 公开接口BankAccount(string accNum, double initBalance) : accountNumber(accNum), balance(initBalance) {}void deposit(double amount) {if (amount > 0) balance += amount;}bool withdraw(double amount) {if (amount > 0 && balance >= amount) {balance -= amount;return true;}return false;}double getBalance() const { return balance; }
};// 使用示例
BankAccount myAccount("123456789", 1000.0);
myAccount.deposit(500.0);
bool success = myAccount.withdraw(200.0);
cout << "Current balance: " << myAccount.getBalance();
输出结果:
Current balance: 1300.0
2. 继承:代码复用的艺术
继承类型与访问控制
继承方式 | 基类public成员 | 基类protected成员 | 基类private成员 |
---|---|---|---|
public | public | protected | 不可访问 |
protected | protected | protected | 不可访问 |
private | private | private | 不可访问 |
class Animal { // 基类
protected:string name;public:Animal(string n) : name(n) {}void eat() { cout << name << " is eating." << endl; }
};class Dog : public Animal { // public继承
public:Dog(string n) : Animal(n) {}void bark() { cout << name << " says: Woof! Woof!" << endl; // 可访问基类protected成员}
};// 使用示例
Dog myDog("Buddy");
myDog.eat(); // 继承自基类
myDog.bark(); // 派生类自有方法
输出结果:
Buddy is eating.
Buddy says: Woof! Woof!
构造与析构顺序
- 构造顺序:基类 → 派生类
- 析构顺序:派生类 → 基类
class Base {
public:Base() { cout << "Base constructor" << endl; }~Base() { cout << "Base destructor" << endl; }
};class Derived : public Base {
public:Derived() { cout << "Derived constructor" << endl; }~Derived() { cout << "Derived destructor" << endl; }
};// 使用示例
{Derived obj;
}
输出结果:
Base constructor
Derived constructor
Derived destructor
Base destructor
菱形继承解决方案
class Person {
public:string name;Person(string n) : name(n) {}
};// 虚继承解决菱形继承问题
class Student : virtual public Person {
public:int studentId;Student(string n, int id) : Person(n), studentId(id) {}
};class Teacher : virtual public Person {
public:string department;Teacher(string n, string dept) : Person(n), department(dept) {}
};class TA : public Student, public Teacher {
public:TA(string n, int id, string dept) : Person(n), Student(n, id), Teacher(n, dept) {} // 直接初始化虚基类
};
3. 多态:同一接口的多种实现
静态多态(编译时)
函数重载
class Calculator {
public:int add(int a, int b) { return a + b; }double add(double a, double b) { return a + b; }string add(string a, string b) { return a + b; }
};// 使用示例
Calculator calc;
cout << calc.add(5, 3) << endl;
cout << calc.add(2.5, 3.7) << endl;
cout << calc.add("Hello, ", "World!") << endl;
输出结果:
8
6.2
Hello, World!
运算符重载
class Vector2D {
public:float x, y;Vector2D(float x, float y) : x(x), y(y) {}// 成员函数形式重载+Vector2D operator+(const Vector2D& other) const {return Vector2D(x + other.x, y + other.y);}// 友元函数形式重载<<friend ostream& operator<<(ostream& os, const Vector2D& v);
};ostream& operator<<(ostream& os, const Vector2D& v) {os << "(" << v.x << ", " << v.y << ")";return os;
}// 使用示例
Vector2D v1(1.0f, 2.0f);
Vector2D v2(3.0f, 4.0f);
Vector2D v3 = v1 + v2;
cout << v1 << " + " << v2 << " = " << v3;
输出结果:
(1, 2) + (3, 4) = (4, 6)
动态多态(运行时)
虚函数与重写
class Shape {
public:virtual void draw() const { // 虚函数cout << "Drawing a generic shape" << endl;}virtual double area() const = 0; // 纯虚函数
};class Circle : public Shape {
private:double radius;
public:Circle(double r) : radius(r) {}void draw() const override { // 重写基类虚函数cout << "Drawing a circle with radius " << radius << endl;}double area() const override {return 3.14159 * radius * radius;}
};// 使用多态
void drawShape(const Shape& shape) {shape.draw();cout << "Area: " << shape.area() << endl;
}// 使用示例
Circle circle(5.0);
drawShape(circle);
输出结果:
Drawing a circle with radius 5
Area: 78.5397
抽象类
class Animal {
public:virtual void makeSound() const = 0; // 纯虚函数
};class Dog : public Animal {
public:void makeSound() const override {cout << "Woof! Woof!" << endl;}
};class Cat : public Animal {
public:void makeSound() const override {cout << "Meow!" << endl;}
};// 使用示例
Animal* animals[] = {new Dog(), new Cat()};
for (Animal* animal : animals) {animal->makeSound();
}
输出结果:
Woof! Woof!
Meow!
4. 友元机制:打破封装边界
class SecretData {
private:int secretCode;string secretMessage;public:SecretData(int code, string msg) : secretCode(code), secretMessage(msg) {}// 声明友元函数friend void displaySecret(const SecretData&);// 声明友元类friend class SecretAccessor;
};// 友元函数实现
void displaySecret(const SecretData& data) {cout << "Code: " << data.secretCode << ", Message: " << data.secretMessage << endl;
}// 友元类实现
class SecretAccessor {
public:void modifySecret(SecretData& data, int newCode, string newMsg) {data.secretCode = newCode;data.secretMessage = newMsg;}
};// 使用示例
SecretData data(123, "Top Secret");
displaySecret(data); // 友元函数访问私有成员SecretAccessor accessor;
accessor.modifySecret(data, 456, "New Secret");
displaySecret(data);
输出结果:
Code: 123, Message: Top Secret
Code: 456, Message: New Secret
5. 综合应用实例
class Vehicle {
protected:string brand;int year;public:Vehicle(string b, int y) : brand(b), year(y) {}virtual void displayInfo() const {cout << brand << " (" << year << ")";}virtual void startEngine() const = 0;
};class Car : public Vehicle {
private:int doors;public:Car(string b, int y, int d) : Vehicle(b, y), doors(d) {}void displayInfo() const override {cout << "Car: ";Vehicle::displayInfo();cout << ", Doors: " << doors << endl;}void startEngine() const override {cout << "Car engine started: Vroom Vroom!" << endl;}
};class Truck : public Vehicle {
private:double payload;public:Truck(string b, int y, double p) : Vehicle(b, y), payload(p) {}void displayInfo() const override {cout << "Truck: ";Vehicle::displayInfo();cout << ", Payload: " << payload << " tons" << endl;}void startEngine() const override {cout << "Truck engine started: RUMBLE RUMBLE!" << endl;}
};// 使用示例
Vehicle* garage[] = {new Car("Toyota", 2022, 4),new Truck("Ford", 2020, 5.5)
};for (Vehicle* v : garage) {v->displayInfo();v->startEngine();cout << endl;
}
输出结果:
Car: Toyota (2022), Doors: 4
Car engine started: Vroom Vroom!Truck: Ford (2020), Payload: 5.5 tons
Truck engine started: RUMBLE RUMBLE!
总结思维导图
关键要点回顾:
- 封装是面向对象的基础,通过访问控制实现数据保护
- 继承提高代码复用率,注意构造/析构顺序和访问控制
- 多态分为静态(编译时)和动态(运行时)两种形式
- 虚函数实现运行时多态,纯虚函数定义接口规范
- 友元机制谨慎使用,它打破了封装边界
- 运算符重载使自定义类型具有内置类型的行为
- 菱形继承问题通过虚继承解决
掌握面向对象三大特性,能够设计出更加灵活、可扩展和可维护的软件系统,是每个C++开发者必须精通的核心理念。
原创技术笔记,转载需注明出处。更多系统编程内容持续更新中…