一、封装:数据与行为的完美结合
1.1 封装的核心概念
封装是将数据 和操作数据的方法绑定在一起的机制,通过访问控制实现信息隐藏。
三大访问权限:
-
public:完全开放访问
-
protected:限于类及其派生类
-
private:仅类内部访问
1.2 封装实现示例
cpp
class BankAccount {
private:
string owner;
double balance;
void logTransaction(const string& msg) const {
cout << "[LOG] " << msg << endl;
}
public:
BankAccount(const string& name, double initial=0)
: owner(name), balance(initial) {
logTransaction("Account created for " + name);
}
void deposit(double amount) {
if(amount <= 0) throw invalid_argument("Invalid amount");
balance += amount;
logTransaction("Deposited " + to_string(amount));
}
double getBalance() const {
return balance;
}
};
封装优势:
-
提高代码安全性
-
降低耦合度
-
增强可维护性
-
简化接口使用
二、继承:代码重用的艺术
2.1 继承的类型与特性
继承方式 | 基类成员访问权限变化 |
---|---|
public | 保持原访问权限 |
protected | public → protected |
private | public/protected → private |
2.2 继承实现示例
cpp
class Shape {
protected:
string color;
public:
explicit Shape(const string& c) : color(c) {}
virtual double area() const = 0;
virtual void draw() const {
cout << "Drawing a " << color << " shape" << endl;
}
};
class Circle : public Shape {
double radius;
public:
Circle(const string& c, double r)
: Shape(c), radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
void draw() const override {
cout << "Drawing a " << color
<< " circle with radius " << radius << endl;
}
};
继承最佳实践:
-
优先使用组合而非继承
-
避免过度继承(继承层次≤3)
-
使用final防止进一步继承
-
注意基类析构函数应为virtual
三、多态:接口与实现的分离
3.1 多态的实现方式
类型 | 实现方式 | 特点 |
---|---|---|
编译时多态 | 函数重载、模板 | 静态绑定 |
运行时多态 | 虚函数、override、final | 动态绑定 |
3.2 多态实现示例
cpp
class Animal {
public:
virtual ~Animal() = default;
virtual void speak() const = 0;
};
class Dog : public Animal {
public:
void speak() const override {
cout << "Woof!" << endl;
}
};
class Cat : public Animal {
public:
void speak() const override {
cout << "Meow!" << endl;
}
};
void animalSound(const Animal& animal) {
animal.speak(); // 运行时多态
}
int main() {
Dog dog;
Cat cat;
animalSound(dog); // 输出: Woof!
animalSound(cat); // 输出: Meow!
}
多态优势:
-
提高代码扩展性
-
增强程序灵活性
-
实现接口与实现分离
-
支持开闭原则
四、三大特性的综合应用
4.1 设计模式示例:策略模式
cpp
class SortStrategy {
public:
virtual ~SortStrategy() = default;
virtual void sort(vector<int>& data) const = 0;
};
class QuickSort : public SortStrategy {
public:
void sort(vector<int>& data) const override {
cout << "Sorting using QuickSort" << endl;
// 实际排序实现...
}
};
class MergeSort : public SortStrategy {
public:
void sort(vector<int>& data) const override {
cout << "Sorting using MergeSort" << endl;
// 实际排序实现...
}
};
class Sorter {
unique_ptr<SortStrategy> strategy;
public:
explicit Sorter(unique_ptr<SortStrategy> strat)
: strategy(move(strat)) {}
void setStrategy(unique_ptr<SortStrategy> strat) {
strategy = move(strat);
}
void executeSort(vector<int>& data) const {
strategy->sort(data);
}
};
4.2 现代C++特性应用
cpp
class SmartDevice {
public:
virtual ~SmartDevice() = default;
virtual void turnOn() = 0;
virtual void turnOff() = 0;
};
class SmartLight final : public SmartDevice {
bool isOn = false;
public:
void turnOn() override {
if(isOn) return;
isOn = true;
cout << "Light turned on" << endl;
}
void turnOff() override {
if(!isOn) return;
isOn = false;
cout << "Light turned off" << endl;
}
void dim(int level) {
cout << "Dimming light to " << level << "%" << endl;
}
};
void controlDevice(SmartDevice& device) {
device.turnOn();
// 使用dynamic_cast进行安全向下转型
if(auto light = dynamic_cast<SmartLight*>(&device)) {
light->dim(50);
}
device.turnOff();
}
五、性能考量与优化
5.1 虚函数开销分析
-
虚表指针:每个对象增加8字节(64位系统)
-
虚表查找:额外间接寻址
-
内联失效:虚函数无法内联
优化策略:
-
避免过度使用虚函数
-
使用final标记不再派生的类
-
考虑CRTP模式(奇异递归模板模式)
5.2 对象切片问题
cpp
class Base {
int data;
public:
virtual void show() const {
cout << "Base: " << data << endl;
}
};
class Derived : public Base {
int extraData;
public:
void show() const override {
cout << "Derived: " << extraData << endl;
}
};
void display(Base obj) { // 对象切片发生
obj.show();
}
int main() {
Derived d;
display(d); // 输出: Base: xxx
}
解决方案:
-
使用指针或引用传递
-
使用智能指针管理对象生命周期
六、设计原则与最佳实践
6.1 SOLID原则应用
原则 | 解释 | 示例 |
---|---|---|
单一职责 | 类只做一件事 | 分离数据存储与业务逻辑 |
开闭原则 | 对扩展开放,对修改关闭 | 使用策略模式 |
里氏替换 | 子类可替换基类 | 遵循is-a关系 |
接口隔离 | 细粒度接口 | 拆分多功能接口 |
依赖倒置 | 依赖抽象 | 使用抽象基类 |
6.2 代码组织建议
7.3 对象生命周期管理
结语
面向对象三大特性是C++编程的基石,正确理解和运用这些特性可以显著提高代码质量。建议在实际开发中:
-
头文件只包含必要声明
-
实现细节放在cpp文件
-
使用命名空间组织相关类
-
遵循单一职责原则
-
优先使用组合而非继承
七、常见问题与解决方案
7.1 菱形继承问题
cppclass A { int data; }; class B : public A {}; class C : public A {}; class D : public B, public C {}; // 数据冗余 // 解决方案:虚继承 class B : virtual public A {}; class C : virtual public A {};
7.2 多继承陷阱
-
避免多继承带来的复杂性
-
使用接口类替代实现继承
-
优先选择单一继承+组合
-
使用RAII原则
-
优先使用智能指针
-
明确所有权关系
-
合理使用封装保护数据
-
谨慎设计继承层次
-
善用多态提高扩展性
-
遵循SOLID设计原则
-
持续优化性能关键路径