代码之家  ›  专栏  ›  技术社区  ›  Greg

C++中访问器方法(吸气剂和设置器)的约定

  •  70
  • Greg  · 技术社区  · 6 年前

    关于C++中的访问方法的一些问题已经被问到了,但是没有一个能够满足我对这个问题的好奇心。

    我尽量避免使用访问器,因为像Stroustrup和其他著名的程序员一样,我认为一个类中有很多访问器是糟糕的OO的标志。在C++中,我可以在大多数情况下添加更多的责任给一个类或者使用朋友关键字来避免它们。但在某些情况下,您确实需要访问特定的类成员。

    有几种可能性:

    1完全不要使用访问器

    我们只需公开各自的成员变量。这是一个不允许使用java的,但是C++社区似乎是可以的。但是,我有点担心,如果一个显式副本或对一个对象的只读(const)引用应该被返回,这是不是太夸张了?

    我不确定它是否来自Java,但我的意思是:

    int getAmount(); // Returns the amount
    void setAmount(int amount); // Sets the amount
    

    三。使用目标C风格的get/set方法

    这有点奇怪,但显然越来越普遍:

    int amount(); // Returns the amount
    void amount(int amount); // Sets the amount
    

    为了让它工作,您必须为您的成员变量找到一个不同的名称。有些人会加下划线,有些人会加上“m”。我也不喜欢。

    你用哪种款式?为什么?

    9 回复  |  直到 12 年前
        1
  •  44
  •   FuleSnabel    10 年前

    从我的角度来看,从400万个C++代码行(从一个项目来看),从维护的角度来看,我会说:

    • 如果成员是不可变的(即。 const )或者是没有依赖关系的简单类(比如具有成员X和Y的点类)。

    • 如果成员是 private 只是跳过getter/setter也是可以的。我还计算了内部 pimpl 私有的

    • 如果成员是 public protected 受保护的 和你一样糟糕 公众的 常数 ,非简单或具有依赖项,然后使用getter/setters。

    我更喜欢备选方案2的风格。因为它更易于搜索(编写可维护代码的关键组件)。

        2
  •  9
  •   AshleysBrain    14 年前

    2) 是最好的IMO,因为它让你的意图最清晰。 set_amount(10) 比…更有意义 amount(10) amount

    公共变量是 通常 一个坏主意,因为没有封装。假设在更新变量时需要更新缓存或刷新窗口?如果你的变量是公共的,那就太糟糕了。如果你有一个set方法,你可以在那里添加它。

        3
  •  7
  •   Omnifarious    14 年前
    1. 当然,实际上,内联显式getter或setter对类实现产生了同样多的底层依赖性。它们只是减少语义依赖。如果您更改了它们,您仍然需要重新编译所有内容。

    2. 这是我使用访问器方法时的默认样式。

    3. 这种款式在我看来太“聪明”了。我确实很少使用它,但只有在我真的希望访问器尽可能感觉像一个变量的情况下才使用它。

    我确实认为有一个简单的变量包,可能有一个构造器,以确保它们都初始化到一些正常的情况。当我这么做的时候,我只是把它变成一个 struct 把一切公之于众。

        4
  •  6
  •   Sadeq    14 年前
    1. pure 数据。

    2. get_/set_ 当我们可以在C++中超载时,这是不必要的。

    3. std::streamString::str std::ios_base::flags 获取/设置_ std::string::get_allocator 因为 std::allocator .

        5
  •  4
  •   Chubsdad    14 年前

    话虽如此,如果这样的设计需要重构,并且源代码可用,我更愿意使用Visitor设计模式。原因是:

    决定允许谁访问其 私人国家

    有机会决定 允许每个实体 对私有国家感兴趣

    清楚地记录了这种外部访问

    基本思想是:

    a) 如果可能的话重新设计,

    (二) 重构使

    1. 所有对类状态的访问都是通过一个众所周知的 个人主义的

    2. 它应该可以配置一些做什么和不做什么 到每个这样的接口,例如 很好 应该被允许,从 外部实体 不允许,外部实体 好的 应允许获取但不允许设置(例如)

        6
  •  2
  •   Cătălin Pitiș    14 年前
    1. 我不会排除访问者的使用。对于一些POD结构来说,这可能是一件好事,但我认为它们是一件好事(一些访问器也可能有额外的逻辑)。

    2. 如果您的代码是一致的,那么命名约定就无关紧要了。如果您使用多个第三方库,它们可能会使用不同的命名约定。所以这是一个品味的问题。

        7
  •  2
  •   Gus    8 年前

    下面的一些东西通常不能很好地利用C++属性:

    struct particle {
        float mass;
        float acceleration;
        float velocity;
    } p;
    

    类的定义来指定一个目的(即使它是一个值,比如 数量

    struct amount
    {
        int value;
    
        amount() : value( 0 ) {}
        amount( int value0 ) : value( value0 ) {}
        operator int()& { return value; }
        operator int()const& { return value; }
        amount& operator = ( int const newvalue )
        {
            value = newvalue;
            return *this;
        }
    };
    

    您可以通过运算符int隐式访问amount中的值。此外:

    struct wage
    {
        amount balance;
    
        operator amount()& { return balance; }
        operator amount()const& { return balance; }
        wage& operator = ( amount const&  newbalance )
        {
            balance = newbalance;
            return *this;
        }
    };
    

    void wage_test()
    {
        wage worker;
        (amount&)worker = 100; // if you like this, can remove = operator
        worker = amount(105);  // an alternative if the first one is too weird
        int value = (amount)worker; // getting amount is more clear
    }
    

        8
  •  1
  •   Name    9 年前

    另一种可能性是:

    int& amount();
    

    我不确定我会推荐它,但它有一个好处,即不寻常的符号可以避免用户修改数据。

    str.length() = 5; // Ok string is a very bad example :)
    

    有时这也许是一个很好的选择:

    image(point) = 255;  
    

    edit::change_amount(obj, val)
    

    这样,危险的/编辑功能就可以在一个单独的名称空间中与其自己的文档分离。这似乎是泛型编程的自然选择。

        9
  •  0
  •   Rok Kralj    11 年前

    让我告诉你另外一个可能性,这似乎是最有节制的。

    需要阅读和修改

    只需声明变量public:

    class Worker {
    public:
        int wage = 5000;
    }
    
    worker.wage = 8000;
    cout << worker.wage << endl;
    

    我只需要阅读

    class Worker {
        int _wage = 5000;
    public:
        inline int wage() {
            return _wage;
        }
    }
    
    worker.wage = 8000; // error !!
    cout << worker.wage() << endl;
    

        10
  •  0
  •   user13985481    5 年前

    class foo {
      private: int bar;
      private: int narf;
      public: foo & bar(int);
      public: int bar();
      public: foo & narf(int);
      public: int narf();
    };
    
    //multi set (get is as expected)
    foo f; f.bar(2).narf(3);