57 C++ 现代C++编程艺术6-类的内部类

C++ 现代C++编程艺术6-类的内部类

C++ 内部类(嵌套类)是定义在另一个类内部的类,主要用于封装关联逻辑、隐藏实现细节或优化代码组织。

一、内部类基础概念

内部类(嵌套类) 是定义在另一个类内部的类,主要用于:

  • 封装关联逻辑:将紧密相关的类组织在一起
  • 隐藏实现细节:限制内部类的可见性
  • 优化代码组织:提高代码的内聚性和可读性
  • 减少命名冲突:通过类作用域隔离标识符
class Outer {
public:
    class Inner {  // 内部类声明 
        // 成员定义
    };
};

二、核心应用场景与代码示例

1. 隐藏派生类(实现工厂模式)

// 基类接口 
class Shape {
public:
    virtual void draw() = 0;
    virtual ~Shape() = default;
};

class ShapeFactory {
public:
    static Shape* createCircle() { 
        return new InnerCircle();  // 返回内部类实例 
    }
private:
    // 私有内部类实现 
    class InnerCircle : public Shape {
    public:
        void draw() override {
            std::cout << "Drawing Circle" << std::endl;
        }
    };
};

int main() {

    // 使用示例 
    Shape* circle = ShapeFactory::createCircle();
    circle->draw();  // 输出: Drawing Circle 
    delete circle;

return 0;
}

2. 模板化内部类(泛型编程)

#include <iostream>
#include <vector>
#include <stdexcept>  // 包含标准异常头文件
 
template <typename T>
class Matrix {
public:
    // 默认构造函数创建空矩阵 
    Matrix() = default;
    
    // 带参数的构造函数
    Matrix(size_t rows, size_t cols) : data(rows, std::vector<T>(cols)) {}
    
    // 模板内部类:行迭代器 
    class RowIterator {
    private:
        T* currentRow;
        size_t rowSize = 0;  // 存储行大小信息 
 
    public:
        explicit RowIterator(T* row, size_t size) 
            : currentRow(row), rowSize(size) {}
        
        // 下标访问运算符 
        T& operator[](size_t col) {
            if (col >= rowSize) {
                throw std::out_of_range("Column index out of range");
            }
            return currentRow[col];
        }
        
        // 只读版本的下标访问
        const T& operator[](size_t col) const {
            if (col >= rowSize) {
                throw std::out_of_range("Column index out of range");
            }
            return currentRow[col];
        }
        
        // 获取行首指针 
        T* begin() { return currentRow; }
        
        // 获取行尾指针 
        T* end() { return currentRow + rowSize; }
        
        // 获取行大小 
        size_t size() const { return rowSize; }
    };
 
    // 矩阵行访问运算符 
    RowIterator operator[](size_t row) {
        if (row >= data.size())  {
            throw std::out_of_range("Row index out of range");
        }
        // 传递行指针和行大小
        return RowIterator(data[row].data(), data[row].size());
    }
    
    // 只读版本的行访问 
    const RowIterator operator[](size_t row) const {
        if (row >= data.size())  {
            throw std::out_of_range("Row index out of range");
        }
        return RowIterator(data[row].data(), data[row].size());
    }
    
    // 安全元素访问接口 
    T& at(size_t row, size_t col) {
        if (row >= data.size())  {
            throw std::out_of_range("Row index out of range");
        }
        if (col >= data[row].size()) {
            throw std::out_of_range("Column index out of range");
        }
        return data[row][col];
    }
    
    // 只读安全访问 
    const T& at(size_t row, size_t col) const {
        if (row >= data.size())  {
            throw std::out_of_range("Row index out of range");
        }
        if (col >= data[row].size()) {
            throw std::out_of_range("Column index out of range");
        }
        return data[row][col];
    }
    
    // 获取行数
    size_t rows() const { return data.size();  }
    
    // 获取列数(假设所有行大小相同)
    size_t cols() const { 
        if (data.empty())  return 0;
        return data[0].size(); 
    }
    
    // 改变矩阵大小 
    void resize(size_t rows, size_t cols) {
        data.resize(rows); 
        for (auto& row : data) {
            row.resize(cols); 
        }
    }
 
private:
    std::vector<std::vector<T>> data;
};
 
int main() {
    try {
        // 创建3x4矩阵
        Matrix<int> mat1(3, 4);
        
        // 初始化矩阵值 
        for (size_t i = 0; i < mat1.rows();  ++i) {
            for (size_t j = 0; j < mat1.cols();  ++j) {
                mat1[i][j] = static_cast<int>(i * mat1.cols()  + j);
            }
        }
        
        // 访问元素 
        auto row = mat1[2];  // 获取第三行 
        int value = row[3];   // 访问第四列元素 
        
        std::cout << "Value at [2][3]: " << value << std::endl;  // 应该输出11 
        
        // 测试边界检查
        try {
            int invalid = mat1[5][2];  // 越界访问 
        } catch (const std::out_of_range& e) {
            std::cout << "Caught exception: " << e.what()  << std::endl;
        }
        
        // 使用默认构造函数创建矩阵 
        Matrix<float> mat2;
        mat2.resize(2,  3);  // 调整大小
        
        // 填充数据 
        for (size_t i = 0; i < mat2.rows();  ++i) {
            for (size_t j = 0; j < mat2.cols();  ++j) {
                mat2[i][j] = static_cast<float>(i * 10 + 0.123);
            }
        }
        
        // 访问元素
        std::cout << "Value at [1][2]: " << mat2[1][2] << std::endl;  // 应该输出 10.123
        
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what()  << std::endl;
        return 1;
    }
    
    return 0;
}

3. 模板特化与友元关系

template<typename T>
class Container {
    T data;
    
    // 每个模板实例独立声明友元
    friend class Iterator;
    
public:
    class Iterator {
    public:
        void reset(Container& c) { 
            c.data = T{};  // 访问外部类私有成员 
        }
        
        const T& get(const Container& c) const {
            return c.data;  // 只读访问 
        }
    };
};
 
// 使用示例 
Container<int> intContainer;
Container<int>::Iterator intIter;
intIter.reset(intContainer);
 
Container<std::string> strContainer;
Container<std::string>::Iterator strIter;
strIter.reset(strContainer);

三、高级应用技巧

  1. 元编程支持

    class TypeTraits {
    public:
        // 类型特征提取内部类 
        template<typename T>
        class TypeInfo {
        public:
            static constexpr bool is_integral = std::is_integral_v<T>;
            static constexpr bool is_pointer = std::is_pointer_v<T>;
            
            static std::string name() {
                if constexpr (is_integral) return "Integral";
                else if constexpr (is_pointer) return "Pointer";
                else return "Unknown";
            }
        };
    };
    
    // 使用示例 
    std::cout << TypeTraits::TypeInfo<int>::name();  // 输出: Integral
    std::cout << TypeTraits::TypeInfo<int*>::name(); // 输出: Pointer 
    
  2. 访问控制模式

    class SecureSystem {
    private:
        int secretKey = 0xDEADBEEF;
        
        // 特权访问内部类
        class PrivilegedAccess {
        public:
            static int getKey(SecureSystem& sys) {
                return sys.secretKey;  // 直接访问私有成员
            }
        };
        
    public:
        // 公开API委托特权访问
        int getPublicKey() {
            return PrivilegedAccess::getKey(*this);
        }
    };
    
    // 使用示例
    SecureSystem system;
    int key = system.getPublicKey();  // 通过受控接口访问
    

四、关键注意事项

  1. 访问权限规则

    访问方向权限要求示例
    内部类→外部类需通过实例访问outerObj.member
    外部类→内部类需声明为友元friend class Outer;
    静态成员访问直接访问Outer::staticMember
  2. 生命周期管理

    class ResourceHolder {
    public:
        class ResourceHandle {
        public:
            ResourceHandle(ResourceHolder& holder) 
                : parent(holder) {}
            
            void useResource() {
                if (!parent.resourceActive) {
                    throw std::runtime_error("Resource unavailable");
                }
                // 使用资源...
            }
            
        private:
            ResourceHolder& parent;  // 持有父类引用 
        };
        
        ResourceHandle getHandle() {
            return ResourceHandle(*this);
        }
        
        ~ResourceHolder() {
            resourceActive = false;  // 使所有handle失效
        }
        
    private:
        bool resourceActive = true;
    };
    
  3. 设计最佳推荐

    1. 封装边界:使用private内部类彻底隐藏实现
    2. 接口隔离:通过公共内部类定义子模块接口
    3. 模板特化:为不同模板实例提供定制化内部类
    4. 循环引用:避免内部类与外部类相互依赖
    5. 编译器影响:注意嵌套深度对编译性能的影响

五、应用场景总结

场景技术方案优势
实现隐藏私有内部类 + 工厂方法完全封装实现细节
泛型迭代器模板内部类 + 运算符重载类型安全遍历
有限继承保护内部类 + 静态工厂控制派生范围
特权访问友元内部类 + 代理接口细粒度权限控制
编译期计算静态成员内部类 + constexpr零开销抽象

内部类应保持职责单一,深度嵌套超过两层时,应考虑重构为独立类。

​ 内部类作为C++强大的封装机制,合理使用可显著提升代码的模块化和类型安全性。在框架设计、模板元编程和接口隔离等场景中,它能提供优雅的解决方案,但需警惕过度使用导致的编译依赖和代码可读性问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值