【问题标题】:Const-correctness of function parameters on API changesAPI 更改时函数参数的常量正确性
【发布时间】:2013-07-02 23:24:11
【问题描述】:

假设我正在使用实现函数foo 的库,我的代码可能如下所示:

void foo(const int &) { }

int main() {
    int x = 1;
    foo(x);
    std::cout << (1/x) << std::endl;
}

一切正常。但现在假设在某一时刻foo 因某种原因被修改或重载。现在我们得到的可能是这样的:

void foo(int & x) {
    x--;
}
void foo(const int &) {}

int main() {
    int x = 1;
    foo(x);
    std::cout << (1/x) << std::endl;
}

BAM。程序突然中断。这是因为我们实际上想要传入的 sn-p 是一个常量引用,但随着 API 的突然变化,编译器选择了我们不想要的版本,程序意外中断。

我们想要的实际上是这样的:

int main() {
    int x = 1;
    foo(static_cast<const int &>(x));
    std::cout << (1/x) << std::endl;
}

通过此修复程序,程序再次开始工作。但是,我必须说我在代码中没有看到很多这样的转换,因为每个人似乎都只是相信不会发生这种类型的错误。此外,这似乎是不必要的冗长,如果有多个参数并且名称开始变长,函数调用就会变得非常混乱。

这是一个合理的担忧吗?我应该如何解决?

【问题讨论】:

  • 这不是const_cast 的用途,它旨在删除一个类型的const 限定。 static_cast 也适用于您的示例。
  • @CaptainObvlious cplusplus.com/doc/tutorial/typecasting 在这里它说“这种类型的转换操纵了对象的常量性,无论是设置还是删除。”这是不正确的吗?
  • @Svalorzen 它可以用于此,但不应该。它不是完成任务的最小工具。该任务的最小工具是static_cast
  • 如果foo( int &amp;arg )foo( const int &amp;arg ) 具有明显不同的语义,我认为API 设计人员是合适的。我认为,在一个理智的宇宙中,你不应该两者都需要。在你可能需要两者的奇怪情况下(例如,由于函数指针类型限制),似乎非 const 版本应该能够直接转发到 const 版本。
  • 所有类型转换都可以添加“常量”到一个类型,但只有const_cast(以及内部使用const_cast的C风格类型转换)可以删除它。移除 const-qualifier 并不仅仅限制

标签: c++ function c++11 arguments constants


【解决方案1】:

如果你改变一个接受 const 引用的函数,使它不再是一个 const,你很可能会破坏事情。这意味着您必须检查调用该函数的每个地方,并确保它是安全的。在这种情况下,进一步拥有两个具有相同名称的函数,一个具有 const 和一个不具有 const 绝对是一个糟糕的计划。

正确的做法是创建一个新函数,它执行x-- 变体,名称与现有函数不同。

任何做这种事情的 API 供应商都应该受到严厉的体罚,如果文档中有一个大通知说“我们已经改变了功能foo,它现在递减x,除非参数被强制转换为 const”。这是人们可以想象的最糟糕的二进制中断之一(就“很难找出问题所在”而言)。

【讨论】:

  • 看起来很奇怪,虽然作为 API 用户没有方便的方法来防止意外错误。将参数转换为 const 似乎是一种相对痛苦但有用的方法,可以避免发生任何变量修改。
  • 你可以首先声明x const,如果main 重要的是它不会改变。但实际上,如果有人在他们的 API 中这样做,他们的 API 将无法升级到新版本。你可以用更少的东西让你的用户感到不安。它需要 4 个次要版本的 Python 才能恢复,因此 Python 3.4 现在向后兼容 2.7 的语法。不,他们不想倒退,但没有人(几乎)使用 3.0 到 3.3,因为您必须修改大量代码(尤其是库)。
  • API 编写器可以像添加重载一样轻松更改函数。或const_cast 离开const。新api就是新api:作者不可信,就是不可信。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多