-3
struct B 
{

};

struct A
{
    operator A&() const;
    operator B&() const;
};


int main()
{
    const A a;
    B& br = a;
    A& ar = a;  
}

为什么我可以创建强制转换运算符 to B&,但不能创建A&.

可能它没有多大意义(可以用它来擦除const修饰符,如示例),但它至少不一致!

4

3 回答 3

4

你不能这样做,因为它被明确禁止。N3290 § 12.3.2 规定:

此类函数称为转换函数。不能指定返回类型。如果转换函数是成员函数,则转换函数的类型(8.3.5)是“不带参数返回转换类型ID的函数”。转换函数永远不会用于将(可能是 cv 限定的)对象转换为(可能是 cv 限定的)相同的对象类型(或对它的引用),转换为该类型的(可能是 cv 限定的)基类(或对它的引用)或(可能是 cv 限定的)void。

(强调我的)

这在注释中进一步讨论:

出于重载决议 (13.3.3.1, 13.3.3.1.4) 以及因此初始化 (8.5) 和显式转换 (5.2.9) 的目的,这些转换被视为标准转换。

这解释了这个决定 - 它会过多地干扰内置机制。(收获甚微)。

如果你真的想要一些非对象的东西constconst唯一聪明的方法是使用复制构造函数构造一个新实例。

作为一种解决方法,您可以引入一个轻量级中介(如智能指针):

struct B {};

struct A {};

namespace {
  B b_inst;
  A a_inst;
}

struct A_wrapper {
  A& inst;
  // This is perfectly fine: const alters the reference, not what it refers to
  operator A&() const { return inst; }
  operator B&() const { return b_inst; }
  A_wrapper() : inst(a_inst) {}
};

int main() {
  const A_wrapper a;
  B& br = a;
  A& ar = a;
}

但实际上,一开始就想做这件事看起来像是代码味道。

于 2012-07-20T15:11:06.043 回答
3

正确的方法是使用const_cast

例如,

#include <iostream>
using namespace std;

void f(int* p) {
  cout << *p << endl;
}

int main(void) {
  const int a = 10;
  const int* b = &a;

  // Function f() expects int*, not const int*
  //   f(b);
  int* c = const_cast<int*>(b);
  f(c);

  // Lvalue is const
  //  *b = 20;

  // Undefined behavior
  //  *c = 30;

  int a1 = 40;
  const int* b1 = &a1;
  int* c1 = const_cast<int*>(b1);

  // Integer a1, the object referred to by c1, has
  // not been declared const
  *c1 = 50;

  return 0;
}
于 2012-07-20T14:18:48.420 回答
3

声明转换为对 self 的引用并不是错误的。您的问题出现在您的引用被初始化的时候。由于引用的类型和初始化表达式的类型相同,因此bound directly永远不会考虑引用和您的用户定义的转换运算符。因此,正常的转换规则适用,而 const 转换使代码格式错误。

无论如何,您所做的基本上是要求自己中弹。如果您不喜欢constness请不要使用它。如果你一直这样做,它永远不会打扰你,但它不会让你结交新朋友。

于 2012-07-20T15:03:35.127 回答