[C++规范] 访问类成员变量的方式:直接访问还是通过成员函数访问?

  • 📢博客主页:https://loewen.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉
  • 📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨


一. 为什么通过成员函数访问类成员变量比直接访问类成员更好

示例:

class MI_HardwareConfig
{
public:
    /// @brief 默认构造
    MI_HardwareConfig();
    
    /// @brief 构造
    /// @param type 硬件类型
    /// @param id 编号
    MI_HardwareConfig::MI_HardwareConfig(ME_HardwareTypeEnum type, int id)
        : m_hardwareType(type), m_id(id){}
        
    ~MI_HardwareConfig();

    /// @brief 获取编号(每种类型的硬件间唯一)
    /// @return
    int Id() const;

    /// @brief 获取硬件类型
    /// @return 
    ME_HardwareTypeEnum Type() const;
    
private:
    /// @brief 硬件类型
    ME_HardwareTypeEnum m_hardwareType;

    /// @brief 轴编号(同类型硬件唯一)
    int m_id;
}; 

在面向对象编程(OOP)中,通过成员函数(如ME_HardwareTypeEnum Type() const;int Id() const;)来访问类的私有或受保护成员(如m_hardwareTypem_id),而不是直接通过公共成员访问,是一种更好的做法。

这种做法有几个优点:

1)封装性:封装是OOP的四大特性之一,它允许你隐藏类的内部实现细节,只通过公共接口(即成员函数)与外界交互。即只要类的公共接口保持不变,你就可以自由地修改类的内部实现(如添加新的私有成员、修改私有成员的逻辑、优化内部算法等),而无需担心使用该类的代码需要修改。这降低了类之间的耦合度,使得系统更加灵活和可维护。

2)安全性:通过将成员变量设为私有或受保护,你可以控制对这些变量的访问。这防止了外部代码直接修改类的状态,从而可能导致类成员变量处于无效的状态,比如上面的轴标号m_id直接被调用时被修改为了负数,后面再使用该成员变量就会出现问题。

3)灵活性:上面提到有数据保护的作用,避免直接访问轴标号m_id意外的被修改为了负数导致后续使用异常,那如果想要该成员变量被外界修改的话,可以通过在调用成员函数返回变量之前,在其内部做逻辑的修改:

// 公共成员函数,用于设置轴标号  
// 这里可以添加逻辑来确保id的有效性  
void setId(int id) {  
    if (id >= 0) { // 假设轴标号不能为负数  
    m_id = id;  
    } else {  
    // 可以在这里处理无效输入,比如抛出异常、记录日志或简单地忽略设置  
    throw std::invalid_argument("Axis ID cannot be negative.");  
    }  
} 

4)易维护性 :如果你需要修改某个成员变量的类型或逻辑(比如添加验证),你只需要修改成员函数内部实现,而不需要修改所有直接访问该变量的代码。这大大减少了代码的维护成本。

5)可扩展性:如果你需要在未来添加更多的功能(比如日志记录、性能监控等),你可以通过修改或添加成员函数来实现,这些新功能的添加并没有改变类的外部接口(即公有成员函数),因此不会影响到使用这个类的外部代码。这就是可扩展性的一个体现。


二. 需要访问的类成员变量较多怎么办

当类成员变量较多时,确实需要编写多个成员函数来访问这些变量,这可能会显得有些繁琐。然而,这是面向对象编程(OOP)中封装原则的一部分,它有助于保持类的内部状态的安全性和一致性。

不过,有几种方法可以在一定程度上简化这个过程,同时仍然保持封装性:

1、使用内联函数

将访问器和修改器声明为内联函数可以减少函数调用的开销。内联函数在编译时会被展开到调用点,从而避免了函数调用的开销。这可以通过在函数声明前添加inline关键字来实现(尽管编译器可能会忽略这个提示)。

2、使用结构体或联合体(如果适用)

如果类的多个成员变量经常一起被访问或修改,并且它们之间具有紧密的逻辑关系,那么考虑将这些成员变量封装到一个结构体或联合体中,然后只提供一个访问这个结构体或联合体的成员函数。然而,这种方法可能会破坏封装性,因为它允许外部代码一次性访问多个内部状态

3、代码生成工具

对于大型项目,可以使用代码生成工具来自动生成访问器和修改器函数。这些工具可以根据类的定义自动生成必要的代码,从而减轻手动编写这些函数的负担。

4、重新考虑设计

如果类的成员变量非常多,以至于访问它们变得非常繁琐,那么可能是时候重新考虑类的设计了。也许可以将类拆分成多个更小的、职责更单一的类,或者通过组合(在主类中声明其他拆分类的对象)和继承来重用代码


下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。
  • 33
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丶布布

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值