繁体   English   中英

* static *成员函数的const和非const版本

[英]const and non-const versions of *static* member functions

我有两个版本的相同的静态成员函数:一个采用指向const的指针参数,并采用指向非const的参数。 我想避免代码重复。
在阅读了一些堆栈溢出问题(这些都是关于非静态成员函数的)之后我想出了这个:

class C {
private:
  static const type* func(const type* x) {
    //long code
  }

  static type* func(type* x) {
      return const_cast<type*>(func(static_cast<const type*>(x)));
  }
public:
  //some code that uses these functions
};

(我知道玩指针通常是一个坏主意,但我正在实现一个数据结构。)

我在libstdc ++中发现了一些代码如下:
注意:这些不是成员函数

static type* local_func(type* x)
{
  //long code
}

type* func(type* x)
{
  return local_func(x);
}

const type* func(const type* x)
{
  return local_func(const_cast<type*>(x));
}

在第一种方法中,代码在一个带有指针到const参数的函数中。
在第二种方法中,代码在一个函数中,该函数接受指向非const的参数。
通常应该使用哪种方法? 两个都正确吗?

最重要的规则是接口函数(公共方法,详细命名空间中的一个以外的自由函数等)不应抛弃其输入的常量。 Scott Meyer是第一个谈论使用const_cast防止重复的人之一,这是一个典型的例子( 如何删除类似的const和非const成员函数之间的代码重复? ):

struct C {
  const char & get() const {
    return c;
  }
  char & get() {
    return const_cast<char &>(static_cast<const C &>(*this).get());
  }
  char c;

};

这是指实例方法而不是静态/自由函数,但原理是相同的。 您注意到非const版本添加了const来调用另一个方法(对于实例方法, this指针是输入)。 然后它最后抛弃了constness; 这是安全的,因为它知道原始输入不是const。

反过来实现这一点非常危险。 如果你抛弃你收到的函数参数的constness,如果传递给你的对象实际上是const,你在UB中冒了很大的风险。 也就是说,如果你调用任何实际改变对象的方法(现在你已经抛弃const就很容易做到),你可以轻松获得UB:

C ++标准,第5.2.11 / 7节[const cast]

[注意:根据对象的类型,通过指针,左值或指向数据成员的指针的写入操作会导致const-qualifier的const_cast,这可能会产生未定义的行为。 - 尾注]

它在私有方法/实现函数中并没有那么糟糕,因为你可能会仔细控制它被调用的方式/时间,但为什么这样做呢? 没有任何好处更危险。

从概念上讲,通常情况下,当你有一个相同函数的const和非const版本时,你只是传递对象的内部引用( vector::operator[]是一个规范的例子),而不是实际上是在改变任何东西,这意味着你写它的方式都是安全的。 但抛弃输入的常量仍然更危险; 虽然你可能不太可能弄乱自己,想象一个团队设置,你用错误的方式写它并且工作正常,然后有人改变实现以改变某些东西,给你UB。

总之,在许多情况下,它可能没有实际的区别,但是有一种正确的方法可以做到这一点,它比替代方案更好: constness 添加输入中 ,并从输出中 删除 constness。

我以前只见过你的第一个版本,所以根据我的经验,这是更常见的习语。

第一个版本对我来说似乎是正确的,而第二个版本可能会导致未定义的行为,如果(A)您将实际的const对象传递给函数和(B) long code写入该对象。 鉴于在第一种情况下,编译器将告诉您,如果您尝试写入对象,我将永远不会推荐选项2。 您可以考虑使用/返回const的独立函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM