C++模块化之内部类

目录

1.引言

2.内部类的访问控制

3.优缺点分析

4.实际运用

4.1.实现复杂数据结构

4.2.封装细节实现

4.3.事件处理和回调

4.4.模板元编程辅助类

4.5. 访问控制和封装

4.6. 代码组织和模块化

5.总结


1.引言

        在C++中,内部类(Nested Class)是一种相对不太常用但却非常强大的编程工具。就是在一个类内部定义另外一个类,注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。

        注意:内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员,不管是public、protected、private。但是外部类不是内部类的友元。

下面是一个简单的内部类的例子:

#include <iostream>  
using namespace std;  
  
class Outer {  
public:  
    int outerValue;  
  
    class Inner {  
    public:  
        void display() {  
            // 直接访问外部类的公有成员  
            cout << "Outer value: " << outerValue << endl;  
        }  
    };  
  
    Inner inner;  
};  
  
int main() {  
    Outer outer;  
    outer.outerValue = 10;  
    outer.inner.display(); // 访问内部类的成员函数  
    return 0;  
}

在这个例子中,Inner类是在Outer类的内部定义的。Inner类可以直接访问Outer类的公有成员outerValue。在main函数中,我们首先创建了Outer类的对象outer,然后设置了它的outerValue成员的值,最后调用了内部类Inner的成员函数display来显示outerValue的值。

2.内部类的访问控制

内部类与外部类之间的访问控制是C++中的一个重要特性。内部类可以访问外部类的私有和保护成员,反之亦然。这使得内部类可以更方便地操作外部类的内部状态。以下是一个例子:

class OuterClass {
private:
    int outerValue;

public:
    OuterClass(int value) : outerValue(value) {}

    class InnerClass {
    public:
        void display(const OuterClass& outer) {
            std::cout << "Outer class value: " << outer.outerValue << std::endl;
        }
    };
};

int main() {
    OuterClass outer(42);
    OuterClass::InnerClass inner;
    inner.display(outer);

    return 0;
}

在这个例子中,InnerClass通过传递一个OuterClass对象的引用来访问其私有成员outerValue。这种设计使得内部类可以直接与外部类进行交互,而不需要暴露外部类的私有成员。

注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。

class A
{
public: 
    class B{
        void foo(){
             cout << k <<endl;//OK
             //cout << h <<endl;// ERROR
        }
     };

private: 
    static int k;
    int h;
};
int A::k=3;

内部类可以现在外部类中声明,然后在外部类外定义:

class A
{
public: 
    class B;

private: 
    static int i;
};

class A::B
{
public:
    void foo(){
        cout << i <<endl;
    }//!!!这里也不需要加A::i.
};

int A::i=3;

3.优缺点分析

优点

        封装性增强:

        内部类可以帮助将一个类的实现细节封装起来,避免外部直接访问这些细节。通过内部类,可以更方便地访问外部类的私有成员,而无需将这些成员暴露给外部世界,从而增强了类的封装性。

        内部类可以声明为private或protected,进一步限制其访问范围,实现更好的信息隐藏。

        模块化:

        内部类使得相关的功能可以集中在一个地方,提高了代码的可读性和维护性。尤其是在实现复杂的数据结构(如树、图)时,内部类可以用来表示节点或边,使得数据结构的实现更加清晰和紧凑。

        作用域控制:

        内部类的作用域被限制在外部类的范围内,这有助于避免命名冲突和不必要的依赖。同时,这种设计也使得内部类的使用更加局部化,减少了全局作用域中的类数量。

        访问控制灵活性:

        内部类可以访问外部类的所有成员(包括私有成员),这为类之间的数据共享和交互提供了便利。同时,通过调整内部类的访问修饰符(如public、protected、private),可以对内部类的访问进行灵活控制。

        实现隐藏:

        在一些需要隐藏实现细节的场景中,内部类可以有效地将这些细节封装起来。例如,在数据库连接池的实现中,可以使用内部类来封装连接的管理逻辑。

缺点

        复杂性增加:

        虽然内部类可以提高封装性和模块化,但它们也可能增加代码的复杂性。当嵌套层次较多时,理解和维护代码可能会变得更加困难。

        可读性问题:

        对于不熟悉内部类设计模式的开发者来说,内部类可能会降低代码的可读性。因此,在使用内部类时,需要提供充分的注释和文档来解释其设计目的和使用方式。

        访问限制:

        尽管内部类可以访问外部类的私有成员,但外部类不能直接访问内部类的私有成员(除非通过内部类的对象)。这可能会在某些情况下限制设计的灵活性。

        编译器支持:

        尽管大多数现代C++编译器都支持内部类,但在一些特殊情况下,可能会遇到编译器特有的问题或限制。因此,在跨平台开发时需要注意编译器之间的差异。

4.实际运用

内部类在实际编程中有着广泛的应用,以下是几个常见的场景:

4.1.实现复杂数据结构

在实现如树、图等复杂数据结构时,内部类可以用来表示节点或边,从而使得数据结构的实现更加清晰和紧凑。例如,在实现二叉树时,可以将节点定义为内部类:

class BinaryTree {  
private:  
    struct Node {  
        int value;  
        Node* left;  
        Node* right;  
        Node(int val) : value(val), left(nullptr), right(nullptr) {}  
    };  
    Node* root;  
public:  
    BinaryTree() : root(nullptr) {}  
    // 添加节点、删除节点等函数  
};

4.2.封装细节实现

在一些需要隐藏实现细节的场景中,内部类可以有效地将这些细节封装起来。例如,在实现一个加密算法,在某种特殊的情况下,我想隐藏这个加密算法实现,那么就可以把这个加密算法封装在类的内部,通过接口提供出来,代码如下:

#include <iostream>
#include <string>

//加密接口
class IDecrypt
{
public:
    virtual std::string  encryptDecrypt(const std::string& input, char key) = 0;
};

//一种加密实现
class CBasicDecrypt : public IDecrypt
{
public:
    std::string encryptDecrypt(const std::string& input, char key) override {
        std::string output = input;
 
        for (size_t i = 0; i < input.length(); ++i) {
            output[i] = input[i] ^ key;
        }
 
        return output;
    }
};


class CMyBusiness
{
    ...

protected:
    //我的加密实现
    class CMyDecrypt : public IDecrypt
    {
     public:
        std::string encryptDecrypt(const std::string& input, char key) override {
            std::string output = input;
 
            for (size_t i = 0; i < input.length(); ++i) {
                output[i] = input[i] | key;
            }
 
            return output;
        }       
    };

public:
    //通过接口给外界使用,隐藏它的实现
    IDecrypt* getDecrypt() {
        return &m_myDecrypt;
    }

private:
    CMyDecrypt  m_myDecrypt;
};

4.3.事件处理和回调

在GUI编程或需要事件处理机制的应用中,内部类常用于实现事件处理和回调函数。例如,在一个按钮点击事件处理中,可以使用内部类来封装事件处理逻辑:

class Button {  
public:  
    class ClickListener {  
    public:  
        virtual void onClick() = 0;  
    };  
private:  
    ClickListener* listener;  
public:  
    void setClickListener(ClickListener* listener) {  
        this->listener = listener;  
    }  
    void click() {  
        if (listener) {  
            listener->onClick();  
        }  
    }  
};

4.4.模板元编程辅助类

        在进行模板元编程时,内部类可以用作辅助类,以提供额外的类型信息和操作。这些内部类有助于实现更复杂的模板逻辑和类型转换。

4.5. 访问控制和封装

        内部类提供了一种灵活的访问控制机制。通过将内部类声明为private或protected,可以限制外部代码对内部类的访问,从而增强类的封装性。同时,内部类可以访问外部类的私有成员,这为实现紧密耦合的类关系提供了便利。

4.6. 代码组织和模块化

        内部类有助于将相关的功能组织在一起,提高代码的可读性和可维护性。通过将辅助类或工具类定义为内部类,可以减少全局命名空间的污染,并使代码结构更加清晰。

5.总结

        综上所述,C++内部类在实际应用中具有广泛的应用场景,包括实现复杂数据结构、封装细节实现、事件处理和回调、模板元编程辅助类以及代码组织和模块化等方面。通过合理使用内部类,可以提高代码的封装性、可读性和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/775986.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PTrade常见问题系列3

量化允许同时运行回测和交易的策略个数配置。 量化允许同时运行回测和交易的策略个数在哪里查看&#xff1f; 在量化服务器/home/fly/config/custom_config_conf文件中&#xff0c;其中运行回测的策略个数由backtest_switch&#xff08;是否限制普通回测个数&#xff09;及ba…

AutoCAD 2022 for Mac/Win版 安装包下载

AutoCAD 2022 是由 Autodesk 开发的一款计算机辅助设计&#xff08;CAD&#xff09;软件。它广泛应用于工程、建筑、制造、动画和媒体娱乐等多个领域。 系统要求&#xff1a; 操作系统&#xff1a;Windows 10 或更高版本。 处理器&#xff1a;Intel 或 AMD 处理器&#xff0c…

算法库应用--寻找最长麦穗

学习贺利坚老师算法库 数据结构例程——串的顺序存储应用_使用顺序串存储身份证号-CSDN博客 本人详细解析博客 串的顺序存储的应用实例二_串的顺序存储应用-CSDN博客 版本更新日志 V1.0: 在原有的基础上, 进行优化名字, 并且有了相应的算法库作为支撑, 我使用了for循环来代替老…

第N7周:seq2seq翻译实战-pytorch复现-小白版

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 理论基础 seq2seq&#xff08;Sequence-to-Sequence&#xff09;模型是一种用于机器翻译、文本摘要等序列转换任务的框架。它由两个主要的递归神经网络&#…

HTML【详解】超链接 a 标签的四大功能(页面跳转、页内滚动【锚点】、页面刷新、文件下载)

超链接 a 标签主要有以下功能&#xff1a; 跳转到其他页面 <a href"https://www.baidu.com/" target"_blank" >百度</a>href&#xff1a;目标页面的 url 地址或同网站的其他页面地址&#xff0c;如 detail.htmltarget&#xff1a;打开目标页面…

全面助力巴西slot游戏包推广本土网盟dsp流量广告优势

全面助力巴西slot游戏包推广本土网盟dsp流量广告优势 在巴西这片充满活力的土地上&#xff0c;电子游戏市场蓬勃发展&#xff0c;成为娱乐产业的重要组成部分。随着网络技术的不断进步和移动互联网的普及&#xff0c;巴西玩家对于电子游戏的热情愈发高涨&#xff0c;游戏市场呈…

Streaming local LLM with FastAPI, Llama.cpp and Langchain

题意&#xff1a; 使用FastAPI、Llama.cpp和Langchain流式传输本地大型语言模型 问题背景&#xff1a; I have setup FastAPI with Llama.cpp and Langchain. Now I want to enable streaming in the FastAPI responses. Streaming works with Llama.cpp in my terminal, but…

google 邮件信息收集

主要介绍通过google和fofax对目标进行邮件信息收集 chrome插件 email-whatsapp-extractor link-klipper-extract-all bulk-url-opener-extension email-whatsapp-extractor 使用正则表达式&#xff0c;获取访问页面内所有的email邮箱和whatsapp号码&#xff0c;以表格的形式导…

C电池 和 D 电池的作用和类型详解及其之间的区别

C 和 D 电池是我们日常生活中必不可少的部件。它们通常用于高功率设备。例如手电筒和玩具。 D 型电池和 C 型电池是两种常见的电池类型。它们是一次性圆柱形电池。您可以在很多设备上使用它们。虽然它们有很多相似之处&#xff0c;但它们也有不同的特点。这些特点使它们适合某…

设置和取消Excel“打开密码”的3种方法

在日常工作中&#xff0c;Excel文件中常常包含敏感数据。为了防止未经授权的访问&#xff0c;给Excel文件设置打开密码是一个非常有效的方法。下面分享3种设置Excel打开密码的方法&#xff0c;以及如何取消这些密码。 先来看看设置Excel打开密码的3种方法。 方法一&#xff1…

CSRF漏洞攻击

05-CSRF 1 CSRF概述 1.1 概述 CSRF (Cross-Site Request Forgery) 跨站请求伪造&#xff0c;也可称为一键式攻击 (one-click-attack)&#xff0c;通常缩写为 CSRF 或者 XSRF。 CSRF 攻击是一种挟持用户在当前已登录的浏览器上发送恶意请求的攻击方法。相对于XSS利用用户对指…

对FPGA开发流程系统的学习

FPGA 开发流程&#xff1a; HDL&#xff08;Hardware Design Language&#xff09;和原理图是两种最常用的数字硬件电路描述方法&#xff0c;HDL 设计法具有更好的可移植性、通用性和模块划分与重用性的特点&#xff0c;在目前的工程设计中被广泛使用。所以&#xff0c;我们在…

JDK新特性之协程

在 JVM 中&#xff0c;java 线程直接映射内核线程&#xff0c;因此 java 线程的创建、销毁和调度都要依赖内核态的操作&#xff08;系统调用&#xff09;。而协程是真正的用户线程&#xff0c;如上图所示很多的协程可以映射很少的几个内核线程&#xff0c;并且协程的创建、销毁…

【kubectl详解】最全的kubectl命令用法

文章目录 简介一.命令帮助翻译1.1.基本命令&#xff08;初学者&#xff09;&#xff1a;1.2.基本命令&#xff08;中级&#xff09;&#xff1a;1.3.部署命令&#xff1a;1.4.群集管理命令&#xff1a;1.5.疑难解答和调试命令&#xff1a;1.6.高级命令&#xff1a;1.7.设置命令…

腾讯混元文生图开源模型推出小显存版本,仅需 6G 显存即可运行

腾讯宣布开源小显存版本的混元文生图模型&#xff0c;降低至 6G 显存即可运行&#xff0c;方便个人电脑本地部署。同时&#xff0c;混元 DiT 模型升级至 1.2 版本&#xff0c;图片质感与构图提升。混元 Captioner 打标模型也正式开源&#xff0c;支持中英文双语&#xff0c;优化…

linux ifconfig未找到命令

linux ifconfig未找到命令 1、使用yum安装net-tools yum install net-toolsyum报未找到命令请查看文章vim未找到命令&#xff0c;且yum install vim安装vim失败 2、安装后使用ifconfig命令 ifconfig

数据库、创建表、修改表

一、数据库 1、登陆数据库 2、创建数据库zoo 3、修改数据库zoo字符集为gbk 4、选择当前数据库为zoo 5、查看创建数据库zoo信息 6、删除数据库zoo 二、创建表 1、创建一个名称为db_system的数据库 2、在该数据库下创建两张表&#xff0c;具体要求如下 员工表 user…

智慧校园-资产管理系统总体概述

智慧校园资产管理系统是面向教育机构设计的一体化数字平台&#xff0c;其核心目标在于通过先进的信息技术手段&#xff0c;全面优化校园内部的资产管理流程。该系统致力于提升资产管理的效率与透明度&#xff0c;同时降低成本并确保所有操作符合财务及审计规范&#xff0c;为校…

高效PD,稳定传输,LDR6023CQ芯片,打造顶级直播体验

在当今市场&#xff0c;一款备受瞩目的直播神器——无线领夹麦克风&#xff08;MIC&#xff09;&#xff0c;正风靡于网红直播、在线教育、专业采访、高清视频录制及视频会议等多个领域。麦克风&#xff0c;这一昔日课堂上的常见设备&#xff0c;已随着科技的飞速发展而焕然一新…

GRPC使用之HelloWorld

使用grpc的好处是提供高效的序列化能力&#xff0c;能够跨语言进行调用。这一节我们来学习grpc的入门应用&#xff0c;整篇文章分成3部分: 接口定义&#xff0c;使用grpc的IDL&#xff0c;创建proto文件&#xff0c;编译/生成grpc文件服务端开发&#xff0c;处理客户端请求&am…