【问题标题】:C++ unexpected implict conversionC++ 意外隐式转换
【发布时间】:2014-09-23 05:53:38
【问题描述】:

以下代码由于char 的隐式转换而编译。我不确定为什么,因为我期望(并且期望失败)的唯一隐式转换是从 char const*size_t

#include <cstddef>

struct foo
{
    int operator[](size_t i) const { return 1; }
    operator char() const { return 'a'; }
};

int main()
{
    foo f;
    f["hello"]; // compilation error desired here
}

这里允许编译的隐式转换是什么?如果我删除operator char 或将其设为explicit,则编译将在所需位置失败。

提取此代码的类确实需要隐式转换和operator[]。那么有没有一种方法可以在不显式转换的情况下防止这种行为?

【问题讨论】:

  • 您是否尝试过添加私人operator[](char const*)

标签: c++ casting


【解决方案1】:

行编译的原因是,通过隐式转换,它可以重新解释为'a'["hello"];,这又与编写*(('a')+("hello"));相同,也可以编译。

标准摘录:

5.2.1 下标:

... 表达式 E1[E2] 与 *((E1)+(E2)) 相同(根据定义)...

不显式转换运算符的最简单解决方法是将有问题的下标运算符声明为已删除:

struct foo
{
  operator char() const { return 'a'; }
  int operator[](size_t i) const { return 1; }

  // prevent accidental use of foo["hello"]
  int operator[](char const*) const = delete;
};

【讨论】:

  • ...并通过等效于*(E2 + E1)E2[E1] 的交换性?我不会说那很明显......
  • @UlrichEckhardt,是的,"hello"[0] 等同于 0["hello"]
  • 确实,这并不明显。它是 C++。有些书充满了 C++ 的陷阱和陷阱。
  • 是的,这很奇怪。那么我可以做 std::vector v; 0[v]; ?还是仅使用常规数组的语法才有效? (foo 中 [] 的重载在这里是一个红鲱鱼)
  • @Jerry101:一些书甚至故意包含它们!
【解决方案2】:
f["hello"]; 

转换为 f.operator [] (index),其中 index 是指向“hello”的指针的值。在您的情况下,它调用运算符 [](size_t i)。因此,编译器不会抱怨是绝对可以的。事实上,索引值将是一个 l;arge 值(指针的值),所以在重载 [] 并检查那里的上边界时最好小心 事实上,如果你有:

char *c = "hello"; // c is a pointer
f[c]; // ok

【讨论】:

  • 嗯,这是完全错误和误导的。 char* 不能隐式转换为 size_t,因此 foo::operator[] 永远不会被选中。而是将f 转换为char,以便它转换为'a'["hello"],这与"hello"['a'] 相同,在ascii 中为"hello"[97]。请在您发布之前查看已接受的答案。
猜你喜欢
  • 1970-01-01
  • 2015-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多