“get()const”与“getAsConst()const”

时间:2008-09-18 21:17:51

标签: c++ coding-style const

有人告诉我他们团队中的C ++风格差异。我对这个主题有自己的观点,但我会对来自所有人的专业缺点感兴趣。

因此,如果你有一个类属性,你希望通过两个getter,一个读/写,另一个readonly(即没有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 个答案:

答案 0 :(得分:10)

在几乎所有情况下,C ++都应该完全能够应对方法A.我总是使用它,我从来没有遇到过问题。

在我看来,方法B是违反OnceAndOnlyOnce的情况。而且,现在你需要弄清楚你是否正在处理const引用来编写第一次编译的代码。

我想这是一个风格化的东西 - 从技术上讲它们都有效,但是MethodA让编译器更加努力。对我来说,这是一件好事。

答案 1 :(得分:8)

嗯,首先,当'this'指针是const时,必须调用getAsConst - 而不是当你想要接收一个const对象时。因此,除了任何其他问题,它还巧妙地被误解了。 (当'this'是非const时,你仍然可以调用它,但这既不在这里也不在那里。)

忽略这一点,getAsConst一无所获,并且使用该接口给开发人员带来了不应有的负担。现在他必须确定他当前是否正在使用const变量,而不是仅仅调用“获取”并知道他正在获得他需要的东西,并且他是否正在抓取的新对象需要是const。后来,如果两个对象由于某些重构而变成非常量,那么他必须切换出他的呼叫。

答案 2 :(得分:4)

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

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

答案 3 :(得分:1)

鉴于标准库设置的样式先例(即begin()和begin()const仅举一个例子),显然方法A是正确的选择。我质疑选择方法B的人的理智。

答案 4 :(得分:1)

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

我们在目前正在编写的代码库中使用了第二种风格的变体,因为我们希望在const和非const使用之间有很大的区别。

在我的具体示例中,我们有getTessellation和getMutableTessellation。它是通过写时复制指针实现的。出于性能原因,我们希望尽可能使用const版本,因此我们将名称缩短,并且我们将其命名为不同的名称,以便人们在不打算写入时不会意外地导致副本。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

我更喜欢第一个。当基本上做同样事情的两件事看起来相同时,它在代码中看起来更好。此外,你很少有一个非const对象,但想要调用const方法,所以这不是一个consern(在最坏的情况下,你只需要一个const_cast<>)。

答案 7 :(得分:0)

第一个允许更改变量类型(无论是否const)而无需进一步修改代码。当然,这意味着没有通知开发人员这可能已经从预期路径发生了变化。因此,您是否重视能够快速重构,还是拥有额外的安全网。

答案 8 :(得分:0)

第二个是与匈牙利符号相关的东西,我个人不要这样,我会坚持第一个方法。

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

答案 9 :(得分:0)

由于你隐藏了这些课程的名称,这种关于风格的食物可能适用也可能不适用:

将这两个对象MethodA和MethodB告诉“get”或“getAsConst”是否有意义?您会将“get”或“getAsConst”作为消息发送给任一对象吗?

我看到它的方式,作为方法的消息/调用者的发送者,是获得该值的人;因此,为了响应此“获取”消息,您将向MethodA / MethodB发送一些消息,其结果是您需要获得的值。

示例:如果MethodA的调用者是SOA中的服务,而MethodA是存储库,则在服务的get_A()内部调用MethodA.find_A_by_criteria(...)。

答案 10 :(得分:0)

我看到MethodB的主要技术缺点是,在将通用代码应用于它时,我们必须将代码加倍以处理const和非const版本。例如:

假设T是一个可订单对象(即,我们可以将T类型的对象与运算符<进行比较),假设我们想要找到两个MethodA之间的最大值(相应的两个MethodB)。

对于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 ;
   }
}

此代码适用于const对象和T类型的非const对象:

// 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和非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 ;
   }
}

结论,通过不信任编译器对const-ness的使用,当一个人应该已经足够时,我们就会自己创建两个通用函数。

当然,有了足够的偏执,第二个模板函数应该被称为getMaxAsConst ...因此,问题会通过所有代码传播...

: - P