C++ 封装详解
一、封装的基本概念
1.1 什么是封装
// 封装的核心思想:隐藏实现细节,提供公共接口
class EncapsulationBasics {
private:
// 数据隐藏:内部实现细节
int internalData;
double sensitiveInfo;
std::vector<int> privateBuffer;
// 私有辅助方法
void validateData(int value) {
if (value < 0 || value > 100) {
throw std::invalid_argument("Value out of range");
}
}
void updateInternalState() {
// 内部状态更新逻辑
sensitiveInfo = internalData * 2.5;
}
public:
// 公共接口:对外提供的功能
void setValue(int value) {
validateData(value); // 内部验证
internalData = value; // 设置值
updateInternalState(); // 更新相关状态
}
int getValue() const {
return internalData; // 受控的访问
}
// 只提供必要的操作,不暴露内部结构
void processData() {
// 用户不需要知道具体如何处理
for (auto& item : privateBuffer) {
item *= 2;
}
}
};
// 封装的好处演示
class BankAccount {
private:
double balance; // 余额不能直接访问
std::string accountNumber;
std::vector<std::string> transactionHistory;
static double interestRate;
// 内部验证方法
bool isValidAmount(double amount) const {
return amount > 0 && amount <= balance;
}
void recordTransaction(const std::string& type, double amount) {
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S");
ss << " - " << type << ": $" << amount;
transactionHistory.push_back(ss.str());
}
public:
BankAccount(const std::string& accNum, double initialDeposit)
: accountNumber(accNum), balance(0) {
if (initialDeposit > 0) {
balance = initialDeposit;
recordTransaction("Initial Deposit", initialDeposit);
}
}
// 安全的取款操作
bool withdraw(double amount) {
if (amount <= 0) {
return false; // 无效金额
}
if (amount > balance) {
return false; // 余额不足
}
balance -= amount;
recordTransaction("Withdrawal", amount);
return true;
}
// 安全的存款操作
void deposit(double amount) {
if (amount > 0) {
balance += amount;
recordTransaction("Deposit", amount);
}
}
// 只读访问
double getBalance() const { return balance; }
// 获取交易历史(返回副本,保护原始数据)
std::vector<std::string> getTransactionHistory() const {
return transactionHistory; // 返回副本
}
};
1.2 封装的层次
class EncapsulationLevels {
// 类级别封装
class ClassLevel {
private:
int privateData; // 只能被本类访问
protected:
int protectedData; // 能被本类和派生类访问
public:
int publicData; // 任何地方都能访问
};
// 模块级别封装(使用命名空间)
namespace Internal {
// 内部实现细节
namespace Detail {
class InternalHelper {
// 不应该被外部使用的类
};
}
// 模块内部接口
class ModuleInterface {
public:
void publicFunction();
};
}
// 文件级别封装(使用匿名命名空间)
namespace {
// 只在当前编译单元可见
class FileLocalClass {
void fileLocalFunction() {}
};
}
};
二、数据封装技术
2.1 Getter和Setter设计
class GetterSetterDesign {
private:
int simpleValue;
double cachedValue;
mutable bool cacheValid;
std::string name;
std::vector<int> data;
public:
// 1. 简单的getter/setter
int getSimpleValue() const { return simpleValue; }
void setSimpleValue(int value) { simpleValue = value; }
// 2. 带验证的setter
bool setName(const std::string& newName) {
if (newName.empty() || newName.length() > 50) {
return false; // 验证失败
}
name = newName;
return true;
}
// 3. 计算属性(懒加载)
double getComputedValue() const {
if (!cacheValid) {
cachedValue = expensiveComputation();
cacheValid = true;
}
return cachedValue;
}
// 4. 返回const引用(避免拷贝)
const std::string& getName() const { return name; }
// 5. 链式调用的setter
GetterSetterDesign& setValue(int value) {
simpleValue = value;
cacheValid = false; // 使缓存无效
return *this;
}
// 6. 属性风格的访问(使用函数对象)
class Property {
private:
int& ref;
std::function<bool(int)> validator;
std::function<void()> onChange;
public:
Property(int& r,
std::function<bool(int)> v = [](int){return true;},
std::function<void()> c = [](){})
: ref(r), validator(v), onChange(c) {}
operator int() const { return ref; }
Property& operator=(int value) {
if (validator(value)) {
ref = value;
onChange();
}
return *this;
}
};
private:
double expensiveComputation() const {
// 模拟昂贵的计算
return simpleValue * 3.14159;
}
};
// 高级属性系统
template<typename T>
class Property {
private:
T value;
std::function<void(const T&, const T&)> onChanged;
std::function<bool(const T&)> validator;
public:
Property(const T& initial = T{}) : value(initial) {}
// 设置变化回调
Property& onChange(std::function<void(const T&, const T&)> callback) {
onChanged = callback;
return *this;
}
// 设置验证器
Property& validate(std::function<bool(const T&)> v) {
validator = v;
return *this;
}
// getter
const T& get() const { return value; }
operator const T&() const { return value; }
// setter
bool set(const T& newValue) {
if (validator && !validator(newValue)) {
return false;
}
T oldValue = value;
value = newValue;
if (onChanged) {
onChanged(oldValue, newValue);
}
return true;
}
Property& operator=(const T& newValue) {
set(newValue);
return *this;
}
};
2.2 不可变对象设计
class ImmutableObject {
// 不可变类设计
class ImmutableString {
private:
const std::string data;
const size_t hashCode;
static size_t computeHash(const std::string& str) {
return std::hash<std::string>{}(str);
}
public:
explicit ImmutableString(const std::string& str)
: data(str), hashCode(computeHash(str)) {}
// 只提供const方法
const std::string& get() const { return data; }
size_t hash() const { return hashCode; }
// 修改操作返回新对象
ImmutableString concat(const ImmutableString& other) const {
return ImmutableString(data + other.data);
}
ImmutableString substring(size_t start, size_t length) const {
return ImmutableString(data.substr(start, length));
}
// 删除赋值运算符
ImmutableString& operator=(const ImmutableString&) = delete;
};
// 不可变集合
template<typename T>
class ImmutableVector {
private:
const std::vector<T> data;
public:
explicit ImmutableVector(std::vector<T> vec)
: data(std::move(vec)) {}
// 只读访问
size_t size() const { return data.size(); }
const T& operator[](size_t index) const { return data[index]; }
// 修改操作返回新对象
ImmutableVector add(const T& item) const {
std::vector<T> newData = data;
newData.push_back(item);
return ImmutableVector(std::move(newData));
}
ImmutableVector remove(size_t index) const {
if (index >= data.size()) {
return *this;
}
std::vector<T> newData = data;
newData.erase(newData.begin() + index);
return ImmutableVector(std::move(newData));
}
// 迭代器(只读)
auto begin() const { return data.begin(); }
auto end() const { return data.end(); }
};
};
三、接口设计与信息隐藏
3.1 最小接口原则
class MinimalInterface {
// 错误示例:过度暴露
class BadDesign {
public:
std::vector<int> data; // 直接暴露内部数据结构
void sortData() { std::sort(data.begin(), data.end()); }
void reverseData() { std::reverse(data.begin(), data.end()); }
void shuffleData() { /* ... */ }
void rotateLeft() { /* ... */ }
void rotateRight() { /* ... */ }
// 太多不必要的公共方法
};
// 正确示例:最小化接口
class GoodDesign {
private:
std::vector<int> data;
// 内部辅助方法
void ensureSorted() {
if (!std::is_sorted(data.begin(), data.end())) {
std::sort(data.begin(), data.end());
}
}
public:
// 只暴露必要的操作
void add(int value) {
data.push_back(value);
}
bool remove(int value) {
auto it = std::find(data.begin(), data.end(), value);
if (it != data.end()) {
data.erase(it);
return true;
}
return false;
}
bool contains(int value) const {
return std::find(data.begin(), data.end(), value) != data.end();
}
size_t size() const { return data.size(); }
bool empty() const { return data.empty(); }
};
};
3.2 Pimpl惯用法(编译防火墙)
// Widget.h - 公共接口
class Widget {
class Impl; // 前向声明
std::unique_ptr<Impl> pImpl; // 指向实现的指针
public:
// 公共接口
Widget();
~Widget(); // 必须在源文件中定义
Widget(const Widget& other);
Widget& operator=(const Widget& other);
Widget(Widget&& other) noexcept;
Widget& operator=(Widget&& other) noexcept;
void doSomething();
int getValue() const;
void setValue(int value);
};
// Widget.cpp - 实现细节
#include "Widget.h"
#include <map>
#include <algorithm>
// 可以包含任何头文件,不会影响使用Widget的代码
class Widget::Impl {
private:
int value;
std::string name;
std::map<std::string, int> cache;
std::vector<double> internalData;
public:
Impl() : value(0), name("default") {}
Impl(const Impl& other)
: value(other.value)
, name(other.name)
, cache(other.cache)
, internalData(other.internalData) {}
void doSomething() {
// 复杂的实现
value++;
cache[name] = value;
internalData.push_back(value * 1.5);
}
int getValue() const { return value; }
void setValue(int v) { value = v; }
};
// Widget成员函数实现
Widget::Widget() : pImpl(std::make_unique<Impl>()) {}
Widget::~Widget() = default; // 必须在Impl完整定义后
Widget::Widget(const Widget& other)
: pImpl(std::make_unique<Impl>(*other.pImpl)) {}
Widget& Widget::operator=(const Widget& other) {
if (this != &other) {
pImpl = std::make_unique<Impl>(*other.pImpl);
}
return *this;
}
Widget::Widget(Widget&& other) noexcept = default;
Widget& Widget::operator=(Widget&& other) noexcept = default;
void Widget::doSomething() { pImpl->doSomething(); }
int Widget::getValue() const { return pImpl->getValue(); }
void Widget::setValue(int value) { pImpl->setValue(value); }
四、访问控制策略
4.1 友元的合理使用
class FriendUsage {
// 运算符重载的友元
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 友元函数用于运算符重载
friend Complex operator+(const Complex& a, const Complex& b);
friend Complex operator*(const Complex& a, const Complex& b);
friend std::ostream& operator<<(std::ostream& os, const Complex& c);
// 友元类用于紧密相关的类
friend class ComplexBuilder;
};
Complex operator+(const Complex& a, const Complex& b) {
return Complex(a.real + b.real, a.imag + b.imag);
}
// Builder模式的友元使用
class ComplexBuilder {
private:
Complex result;
public:
ComplexBuilder& setReal(double r) {
result.real = r; // 可以访问Complex的私有成员
return *this;
}
ComplexBuilder& setImag(double i) {
result.imag = i;
return *this;
}
Complex build() { return result; }
};
// Attorney-Client惯用法(受控友元)
class Document {
private:
std::string content;
void internalSave() { /* ... */ }
void internalLoad() { /* ... */ }
friend class DocumentAttorney;
};
class DocumentAttorney {
private:
friend class DocumentSaver;
friend class DocumentLoader;
static void save(Document& doc) { doc.internalSave(); }
static void load(Document& doc) { doc.internalLoad(); }
};
class DocumentSaver {
public:
void saveDocument(Document& doc) {
DocumentAttorney::save(doc); // 受控访问
}
};
};
4.2 嵌套类的封装
class NestedClassEncapsulation {
class Container {
private:
// 私有嵌套类,完全隐藏实现
class Node {
int data;
Node* next;
public:
Node(int d) : data(d), next(nullptr) {}
};
Node* head;
public:
// 公共嵌套类,作为接口的一部分
class Iterator {
private:
Node* current;
Iterator(Node* node) : current(node) {}
friend class Container;
public:
int operator*() const { return current->data; }
Iterator& operator++() {
current = current->next;
return *this;
}
bool operator!=(const Iterator& other) const {
return current != other.current;
}
};
Container() : head(nullptr) {}
void push_front(int value) {
Node* newNode = new Node(value);
newNode->next = head;
head = newNode;
}
Iterator begin() { return Iterator(head); }
Iterator end() { return Iterator(nullptr); }
};
};
五、高级封装技术
5.1 CRTP(奇异递归模板模式)封装
template<typename Derived>
class CRTPBase {
protected:
// 受保护的实现细节
void implementationDetail() {
std::cout << "Base implementation\n";
}
public:
// 公共接口
void publicInterface() {
// 前置处理
std::cout << "Before derived\n";
// 调用派生类实现
static_cast<Derived*>(this)->implementation();
// 后置处理
std::cout << "After derived\n";
}
// 提供默认实现
void implementation() {
implementationDetail();
}
};
class CRTPDerived : public CRTPBase<CRTPDerived> {
public:
// 覆盖实现
void implementation() {
std::cout << "Derived implementation\n";
}
};
// Mixin模式的封装
template<typename T>
class Printable {
public:
void print() const {
static_cast<const T*>(this)->printImpl();
}
protected:
void printImpl() const {
std::cout << "Default print\n";
}
};
template<typename T>
class Serializable {
public:
std::string serialize() const {
return static_cast<const T*>(this)->serializeImpl();
}
protected:
std::string serializeImpl() const {
return "default";
}
};
class MyClass : public Printable<MyClass>,
public Serializable<MyClass> {
public:
void printImpl() const {
std::cout << "MyClass print\n";
}
std::string serializeImpl() const {
return "MyClass data";
}
};
5.2 策略模式封装
class StrategyEncapsulation {
// 策略接口
class SortStrategy {
public:
virtual ~SortStrategy() = default;
virtual void sort(std::vector<int>& data) = 0;
};
// 具体策略(实现细节)
class QuickSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
// QuickSort实现
std::sort(data.begin(), data.end());
}
};
class MergeSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
// MergeSort实现
std::stable_sort(data.begin(), data.end());
}
};
// 上下文类
class DataProcessor {
private:
std::vector<int> data;
std::unique_ptr<SortStrategy> sortStrategy;
public:
DataProcessor()
: sortStrategy(std::make_unique<QuickSort>()) {}
void setSortStrategy(std::unique_ptr<SortStrategy> strategy) {
sortStrategy = std::move(strategy);
}
void addData(int value) {
data.push_back(value);
}
void process() {
sortStrategy->sort(data); // 使用策略
}
void display() const {
for (int val : data) {
std::cout << val << " ";
}
std::cout << "\n";
}
};
};
5.3 代理模式封装
class ProxyPattern {
// 真实对象接口
class Image {
public:
virtual ~Image() = default;
virtual void display() = 0;
virtual std::string getName() const = 0;
};
// 真实对象(重量级)
class RealImage : public Image {
private:
std::string filename;
std::vector<unsigned char> imageData;
void loadFromDisk() {
std::cout << "Loading image: " << filename << "\n";
// 模拟加载大图片
imageData.resize(1024 * 1024); // 1MB
}
public:
explicit RealImage(const std::string& file)
: filename(file) {
loadFromDisk();
}
void display() override {
std::cout << "Displaying: " << filename << "\n";
}
std::string getName() const override {
return filename;
}
};
// 代理对象(轻量级)
class ProxyImage : public Image {
private:
std::string filename;
mutable std::unique_ptr<RealImage> realImage;
public:
explicit ProxyImage(const std::string& file)
: filename(file) {}
void display() override {
if (!realImage) {
realImage = std::make_unique<RealImage>(filename);
}
realImage->display();
}
std::string getName() const override {
return filename; // 不需要加载真实图片
}
};
// 智能指针代理
template<typename T>
class SmartProxy {
private:
T* ptr;
mutable size_t accessCount;
public:
explicit SmartProxy(T* p) : ptr(p), accessCount(0) {}
T* operator->() const {
++accessCount;
std::cout << "Access count: " << accessCount << "\n";
return ptr;
}
T& operator*() const {
++accessCount;
return *ptr;
}
size_t getAccessCount() const { return accessCount; }
};
};
六、封装的最佳实践
6.1 接口稳定性
class InterfaceStability {
// 版本1:初始设计
class ServiceV1 {
private:
struct Impl;
std::unique_ptr<Impl> pImpl;
public:
ServiceV1();
~ServiceV1();
void operation1();
void operation2();
};
// 版本2:添加新功能(保持向后兼容)
class ServiceV2 {
private:
struct Impl;
std::unique_ptr<Impl> pImpl;
public:
ServiceV2();
~ServiceV2();
// 保留原有接口
void operation1();
void operation2();
// 新增功能
void operation3();
// 带默认参数的新版本
void operation1(int param = 0);
};
// 使用版本控制
class VersionedAPI {
public:
enum class Version { V1, V2, V3 };
private:
Version currentVersion;
public:
explicit VersionedAPI(Version v = Version::V3)
: currentVersion(v) {}
void execute() {
switch (currentVersion) {
case Version::V1:
executeV1();
break;
case Version::V2:
executeV2();
break;
case Version::V3:
executeV3();
break;
}
}
private:
void executeV1() { /* V1 implementation */ }
void executeV2() { /* V2 implementation */ }
void executeV3() { /* V3 implementation */ }
};
};
6.2 封装的度量标准
class EncapsulationMetrics {
// 高内聚的类
class HighCohesion {
private:
std::string data;
// 所有方法都操作同一组数据
void validateData() { /* ... */ }
void processData() { /* ... */ }
void formatData() { /* ... */ }
public:
void setData(const std::string& d) {
data = d;
validateData();
}
std::string getData() {
processData();
formatData();
return data;
}
};
// 低耦合的设计
class LowCoupling {
// 依赖接口而不是具体实现
class DataSource {
public:
virtual ~DataSource() = default;
virtual std::string read() = 0;
};
class DataProcessor {
private:
std::unique_ptr<DataSource> source;
public:
explicit DataProcessor(std::unique_ptr<DataSource> s)
: source(std::move(s)) {}
void process() {
std::string data = source->read(); // 低耦合
// 处理数据
}
};
};
// 信息隐藏度量
class InformationHiding {
public:
// 公共接口复杂度:低
void simpleOperation();
private:
// 实现复杂度:高(被隐藏)
void complexAlgorithm1();
void complexAlgorithm2();
void complexAlgorithm3();
// 数据复杂度:高(被隐藏)
std::map<std::string, std::vector<int>> complexData;
std::unordered_map<int, std::shared_ptr<void>> cache;
};
};
6.3 封装的性能考虑
class PerformanceConsiderations {
// 内联封装
class InlineEncapsulation {
private:
int value;
public:
// 简单的getter/setter可以内联
inline int getValue() const { return value; }
inline void setValue(int v) { value = v; }
// 复杂操作不应内联
void complexOperation(); // 定义在源文件中
};
// 零成本抽象
template<typename T>
class ZeroCostWrapper {
private:
T value;
public:
explicit ZeroCostWrapper(T v) : value(v) {}
// 编译时优化掉的封装
T& get() { return value; }
const T& get() const { return value; }
// 操作符重载保持自然语法
operator T&() { return value; }
operator const T&() const { return value; }
};
// 缓存友好的封装
class CacheFriendly {
private:
// 热数据放在一起
struct HotData {
int frequently_used1;
int frequently_used2;
double frequently_used3;
} hot;
// 冷数据分离
struct ColdData {
std::string rarely_used1;
std::vector<int> rarely_used2;
};
std::unique_ptr<ColdData> cold;
public:
int getFrequent() const { return hot.frequently_used1; }
const std::string& getRare() {
if (!cold) {
cold = std::make_unique<ColdData>();
}
return cold->rarely_used1;
}
};
};
6.4 测试友好的封装
class TestFriendlyEncapsulation {
// 依赖注入
class EmailService {
public:
virtual ~EmailService() = default;
virtual void sendEmail(const std::string& to,
const std::string& message) = 0;
};
class UserManager {
private:
std::unique_ptr<EmailService> emailService;
public:
explicit UserManager(std::unique_ptr<EmailService> service)
: emailService(std::move(service)) {}
void registerUser(const std::string& email) {
// 业务逻辑
emailService->sendEmail(email, "Welcome!");
}
};
// 测试用的Mock对象
class MockEmailService : public EmailService {
public:
mutable std::vector<std::pair<std::string, std::string>> sentEmails;
void sendEmail(const std::string& to,
const std::string& message) override {
sentEmails.push_back({to, message});
}
};
// 部分暴露用于测试
class TestableClass {
private:
int privateState;
protected:
// 为测试类提供访问
virtual int getStateForTesting() const { return privateState; }
public:
void publicMethod() {
privateState = 42;
}
friend class TestableClassTest; // 测试友元
};
};