成员函数可以直接访问数据成员,getter和setter不是多此一举吗

了解一下封装(encapsulation)及优势:

packaging of data and functions that work on that data together

将数据和处理该数据的函数打包在一起

via access specifiers to hide information

通过访问说明符隐藏信息

separation of interface and implementation

接口与实现分离

easier to use and reduce the complexity of your programs

更易于使用并降低程序的复杂性

help protect your data and prevent misuse

帮助保护您的数据并防止滥用

use objects without understanding how they work

使用对象时无须了解其工作方式

easier to change, easier to debug

更容易更改,更容易调试

class or file can implement encapsulation

类或文件可以实现封装

demo code:

class MyArray
{
    int* m_arr;
    int m_size;
    int m_capacity;
public:
    MyArray(int size,int capacity);
    ~MyArray();
    void sort(); // sort可以随时改变实现(快速排序或其它排序)
};

封装可以隔离接口和实现,成员函数的具体实现的改变不影响接口使用的代码。

那如果数据成员更改的话,有什么方式不影响接口使用的代码?

使用access function:

#include 

class Something
{
public:
    int m_value1;
    int m_value2;
    int m_value3;
};

int main()
{
    Something something;
    something.m_value1 = 5;
    std::cout << something.m_value1 << '
';
}

While this program works fine, what would happen if we decided to rename m_value1, or change its type? We’d break not only this program, but likely most of the programs that use class Something as well!

虽然这个程序运行良好,但如果我们决定重命名m_value1或更改其类型,会发生什么情况?我们不仅要破坏这个程序,而且可能还要破坏大多数使用class的程序!

Encapsulation gives us the ability to change how classes are implemented without breaking all of the programs that use them.

封装使我们能够在不破坏所有使用类的程序的情况下更改类的实现方式。

Here is the encapsulated version of this class that uses functions to access m_value1:

下面是该类的封装版本,它使用函数访问m_value1:

#include 

class Something
{
private:
    int m_value1;
    int m_value2;
    int m_value3;

public:
    void setValue1(int value) { m_value1 = value; }
    int getValue1() { return m_value1; }
};

int main()
{
    Something something;
    something.setValue1(5);
    std::cout << something.getValue1() << '
';
}

Now, let’s change the class’s implementation:

现在,让我们更改类的实现:

#include 

class Something
{
private:
    int m_value[3]; // note: we changed the implementation of this class!

public:
    // We have to update any member functions to reflect the new implementation
    void setValue1(int value) { m_value[0] = value; }
    int getValue1() { return m_value[0]; }
};

int main()
{
    // But our program still works just fine!
    Something something;
    something.setValue1(5);
    std::cout << something.getValue1() << '
';
}

Note that because we did not alter any of the function headers (return type, name, or parameters) in our class’s public interface, our program that uses the class continues to work without any changes.

请注意,因为我们没有更改类的公共接口中的任何函数头(返回类型、名称或参数),所以使用该类的程序可以继续工作,没有任何更改。

There is a fair bit of discussion around in which cases access functions should be used or avoided. Although they don’t violate encapsulation, some developers would argue that use of access functions violates good OOP class design.

关于在哪些情况下应该使用或避免访问(access)函数,有很多讨论。尽管它们没有违反封装,但一些开发人员会争辩说,使用访问函数违反了良好的OOP类设计。

For now, we’ll recommend a pragmatic approach. As you create your classes, consider the following:

目前,我们将推荐一种务实的方法。创建类时,请考虑以下事项:

If nobody outside your class needs to access a member, don’t provide access functions for that member.

如果类外没有人需要访问成员,请不要为该成员提供访问函数。

If someone outside your class needs to access a member, think about whether you can expose a behavior or action instead.

如果您的类以外的人需要访问成员,请考虑是否可以公开行为或操作。

If you can’t, consider whether you can provide only a getter.

如果不能,请考虑是否只能提供一个getter。

ref

https://www.learncpp.com/cpp-tutorial/access-functions-and-encapsulation/

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章