【问题标题】:c++ type cast operator overloading and implicit conversionsc++ 类型转换运算符重载和隐式转换
【发布时间】:2015-02-03 20:13:46
【问题描述】:

如果我重载类型转换运算符,当需要隐式转换并且找不到转换时,我会遇到编译错误。考虑一个简单的例子,我有一个包含类型(在本例中为 long long)的包装类:

class my_wrapper
{
    long long state;

public:
    my_wrapper(long long _in) : state(_in) {}

    my_wrapper& operator=(const long long rhs)
    {
        state = rhs;
        return *this;
    }

    operator long long()
    {
        return state;
    }
};

现在的问题是,如果我想将代码转换为其他内容(例如 void* ...假设我为此使用 64 位),如果不指定两个转换,以下内容将不起作用:

my_wrapper x1 = my_wrapper(5ll);
void* i1 = (void *) x1; // Compile Error: no suitable conversion function exists
void* i1 = (void *) (long long) x1; // Works

对比如果我写了类似的东西:

long long i1 = 5ll;
void* i2 = (void *) i1; // Works

没什么大不了的,只是好奇如果没有其他转换,是否可以指定“operator long long()”作为默认值。

【问题讨论】:

  • 不要在 C++ 中使用 C 样式转换。曾经。他们可以做与您期望的完全不同的事情。
  • 同样的原因你不能写(void*)2.5,或多或少。
  • 为什么在 C++ 中使用void*? :/ 有一些 C 库可以使用吗?你不能改为通过&x1 吗?

标签: c++ casting overloading


【解决方案1】:

[over.match.conv]/(1.1):

考虑S及其基类的转换函数。 那些不隐藏在S中的非显式转换函数 并产生类型T 或可以通过a转换为类型T的类型 标准转换序列 (13.3.3.1.1) 是候选函数。

从整数类型到void*1没有标准的转换顺序,因此转换运算符不是候选的。

您可以尝试转换运算符模板:

template <typename T>
operator T()
{
    return T(state);
}

1 值为 0 的整数文字是例外。

【讨论】:

  • 那不是必须是 reinterpret_cast&lt;T&gt;(state) (这在模板中确实是一件非常危险的事情)才能转换为 void * 工作吗?
  • @cdhowie 我只是也这么想。但是T(state) 就足够了。 (虽然按照定义它具有相同的效果)
  • 谢谢。这似乎可以解决问题。 reinterpret_cast(state) 有一个编译时错误,说它不能从 __int64 转换为 __int64,而 T(state) 没有。保留 longlong() 函数使 C++ 风格成为一种工作。
【解决方案2】:

由于(void *)x1 有效地为您提供x1.state 的地址 你可以简单地实现一个void * cast 操作符。

像这样:

operator void *()
{
    return &state;
}

这样做的缺点是您现在也可以隐式my_wrapper 转换为void *

幸运的是,您可以在 C++11 中通过使用 explicit 说明符来防止这种情况发生:

explicit operator void *()
{
    return &state;
}

【讨论】:

  • 是的,我希望避免这样做。 void* 只是一种情况。不过还是谢谢。
  • @user3799309 为什么还是void *
猜你喜欢
  • 2014-08-18
  • 2010-12-09
  • 1970-01-01
  • 2013-11-21
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多