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

“get()const”与“getasconst()const”

  •  1
  • paercebal  · 技术社区  · 16 年前

    有人告诉我他们团队中的C++风格差异。我对这个问题有自己的看法,但我会感兴趣的 赞成的意见 欺骗 来自每个人。

    因此,如果您有一个类属性想要通过两个getter公开,一个读/写,另一个只读(即没有set方法)。至少有两种方法可以做到:

    class T ;
    
    class MethodA
    {
       public :
          const T & get() const ;
          T & get() ;
    
          // etc.
    } ;
    
    class MethodB
    {
       public :
          const T & getAsConst() const ;
          T & get() ;
    
          // etc.
    } ;
    

    每种方法的优缺点是什么?

    我更感兴趣的是C++技术/语义的原因,但风格的原因也受到欢迎。

    注意 MethodB 有一个主要的技术缺陷(提示:在通用代码中)。

    11 回复  |  直到 16 年前
        1
  •  8
  •   moswald Jarod42    16 年前

    好吧,首先,盖茨康斯特 必须 当“this”指针为常量时调用,而不是在您希望接收常量对象时调用。所以,除了其他问题外,它还被巧妙地误称了。(当“this”不是常量时,您仍然可以调用它,但它既不在这里也不在那里。)

    忽略这一点,getasconst不会给您带来任何收益,并且会给使用该接口的开发人员带来不必要的负担。现在他必须确定他是否正在使用常量变量,以及他正在获取的新对象是否需要常量,而不是仅仅调用“get”并知道他正在获取所需的内容。稍后,如果两个对象由于某种重构而变为非常量,那么他必须关闭他的调用。

        2
  •  10
  •   Arkadiy    16 年前

    在任何情况下,C++都应该能够很好地处理方法A。我总是用它,从来没有遇到过问题。

    在我看来,方法B是一个违反原则的案例。现在,您需要弄清楚是否要处理const引用来编写第一次编译的代码。

    我想这是一个风格化的东西——从技术上讲,它们都有效,但是methoda使编译器工作起来有点困难。对我来说,这是件好事。

        3
  •  4
  •   Dima    16 年前

    就我个人而言,我更喜欢第一种方法,因为它使接口更加一致。另外,对我来说getAsConst()听起来和getAsInt()一样愚蠢。

    另一个注意事项是,在将非常量引用或非常量指针返回到类的数据成员之前,确实应该三思而后行。这是一个邀请人们利用您的类的内部工作,这在理想情况下应该是隐藏的。换句话说,它破坏了封装。我将使用get()const和set(),并且只在没有其他方法或真正有意义时返回一个非const引用,例如授予对数组或矩阵元素的读/写访问权。

        4
  •  1
  •   Greg Rogers    16 年前

    考虑到标准库设置的样式先例(即begin()和begin()const只命名一个示例),显然方法A是正确的选择。我质疑选择方法B的人的理智。

        5
  •  1
  •   tfinniga    16 年前

    所以,第一种风格通常更可取。

    不过,在我目前正在研究的代码库中,我们确实使用了第二种样式的变体,因为我们希望在const和non-const用法之间有很大的区别。

    在我的具体示例中,我们有getEssellation和getMutableTessellation。它是用一个copy-on-write指针实现的。出于性能方面的考虑,我们希望尽可能使用const版本,因此我们缩短了名称,并将其改为其他名称,这样人们就不会在不想写的情况下意外地生成副本。

        6
  •  0
  •   William Keller    16 年前

    虽然你的问题似乎只涉及一种方法,但我很乐意提供我对风格的意见。就个人而言,出于风格原因,我更喜欢前者。大多数IDE都会弹出函数的类型签名。

        7
  •  0
  •   Leon Timmermans    16 年前

    我更喜欢第一个。在代码中,当基本上做相同事情的两件事情看起来相同时,它看起来更好。此外,很少有非const对象,但希望调用const方法,因此这不是什么后果(在最坏的情况下,您只需要一个const cast<gt;)。

        8
  •  0
  •   jdmichal    16 年前

    第一个允许更改变量类型(无论是否 const 或者不)不需要进一步修改代码。当然,这意味着没有通知开发人员这可能已经偏离了预期的路径。所以,无论你看重的是能够快速重构,还是拥有额外的安全网。

        9
  •  0
  •   INS    16 年前

    第二个与匈牙利符号有关,我个人认为 不要 就像这样,我会坚持 第一 方法。

    我不喜欢匈牙利符号,因为它增加了我在编程中通常讨厌的冗余。这只是我的意见。

        10
  •  0
  •   moffdub    16 年前

    由于您隐藏了类的名称,因此考虑样式的食物可能适用,也可能不适用:

    告诉这两个对象methoda和methodb“get”或“getasconst”有意义吗?您会将“get”或“getasconst”作为消息发送到任一对象吗?

    在我看来,作为方法的消息/调用程序的发送者, 是获取值的消息;因此,为了响应此“获取”消息,您将向methoda/methodb发送一些消息,其结果是需要获取的值。

    例如:如果methoda的调用者是SOA中的服务,而methoda是存储库,那么在该服务的get_a()中,调用methoda.find_a_by_criteria(…)。

        11
  •  0
  •   paercebal    16 年前

    我所看到的方法B的主要技术缺陷是,在对其应用泛型代码时,必须将代码加倍以处理const和non-const版本。例如:

    假设t是一个可排序的对象(也就是说,我们可以用操作符<与t类型的对象进行比较),假设我们想找到两个方法a(resp)之间的最大值。两种方法b)。

    对于methoda,我们只需要编码:

    template <typename T>
    T & getMax(T & p_oLeft, T & p_oRight)
    {
       if(p_oLeft.get() > p_oRight.get())
       {
          return p_oLeft ;
       }
       else
       {
          return p_oRight ;
       }
    }
    

    此代码既适用于常量对象,也适用于T类型的非常量对象:

    // Ok
    const MethodA oA_C0(), oA_C1() ;
    const MethodA & oA_CResult = getMax(oA_C0, oA_C1) ;
    
    // Ok again
    MethodA oA_0(), oA_1() ;
    MethodA & oA_Result = getMax(oA_0, oA_1) ;
    

    当我们想要将这个简单的代码应用于遵循methodb约定的内容时,问题就出现了:

    // NOT Ok
    const MethodB oB_C0(), oB_C1() ;
    const MethodB & oB_CResult = getMax(oB_C0, oB_C1) ; // Won't compile
    
    // Ok
    MethodA oB_0(), oB_1() ;
    MethodA & oB_Result = getMax(oB_0, oB_1) ;
    

    要使methodb同时在const和non-const版本上工作,我们必须使用已经定义的getmax,但要向其添加以下版本的getmax:

    template <typename T>
    const T & getMax(const T & p_oLeft, const T & p_oRight)
    {
       if(p_oLeft.getAsConst() > p_oRight.getAsConst())
       {
          return p_oLeft ;
       }
       else
       {
          return p_oRight ;
       }
    }
    

    结论,由于不信任编译器的常量使用,当一个函数应该足够时,我们就需要创建两个泛型函数。

    当然,如果有足够的偏执,第二个模板函数应该被称为getmaxasconst…因此,这个问题会通过所有的代码传播出去…

    -P

    推荐文章