文章预览:
  • 一. 为什么通过成员函数访问类成员变量比直接访问类成员更好
  • 二. 需要访问的类成员变量较多怎么办



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

示例:

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;
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.

在面向对象编程(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.");  
    }  
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

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

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


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

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

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

1、使用内联函数

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

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

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

3、代码生成工具

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

4、重新考虑设计

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


下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。