【问题标题】:What does operator float*() do?运算符 float*() 有什么作用?
【发布时间】:2014-08-07 07:36:06
【问题描述】:

我一直在查看源代码,试图了解有关 C++ 的更多信息,但遇到了一些看起来令人困惑的代码。我无法通过玩弄它来弄清楚它的用途。

请谁能解释一下操作符 float *() 的作用以及它是如何使用的?

类向量 { 民众: 浮动 x,y,z; Vector() : x(0), y(0), z(0){ } Vector( float x, float y, float z ) : x(x), y(y), z(z){ } operator float*(){ return &x; } operator const float *(){ return &x; }

我已经搜索过 StackOverflow,它看起来像是一个转换运算符,但我仍然不确定它的实际作用以及它为什么有用。

亲切的问候,

【问题讨论】:

  • 到目前为止,没有一个答案可以解释为什么它转换为float* 而不是float。非常量可能是故意破坏封装的愿望,但为什么有人会写const float * 转换? ---> 啊哈,刚刚看到马特关于假设 x,y,z 在内存中是连续的这一点的评论。好的,可疑的设计,但我现在明白了:-)
  • @Darren 我不会试图解释它,因为我不能。这简直是​​个坏主意。我怀疑原作者想为向量公开一个类似数组的接口,但这是一个坏主意,因为我的答案(以及更多)下面的 cmets 中提到的原因。

标签: c++ class operator-overloading overloading conversion-operator


【解决方案1】:

operator <em>type_name</em> 声明了一个隐式转换 运算符。换句话说,当您尝试(隐式)将您的类型的对象转换为 float* 时调用此函数——例如在赋值中:

Vector x(1, 2, 3);
float* f = x;
assert(*f == 1);

不用说,这种特殊的转换非常糟糕,因为它的效果非常不直观,并且很容易导致无法找到错误。隐式转换通常应该小心处理,因为它们隐藏了潜在的混淆语义。但是它们可以很好地与应该可以互换使用的类型一起使用,并且转换不会造成伤害。

例如,考虑您编写自己的integer 和complex 类的情况。从integer 到complex 的转换是无害的,因为每个整数都是复数(但不是反之亦然)。所以隐式转换 integer → complex 是安全的。

【讨论】:

  • 支持它很糟糕。
  • 更安全的选择是:float &operator[]( int n){ return (&x)[n]; }
  • @MattMcNabb 假设这确实是类的全部定义(或者至少它没有虚拟成员和基类),那么它们实际上是保证是连续的并且按照它们被声明的顺序,因为它是一个标准布局结构。
  • @Matt McNabb 保证数据成员的顺序。
  • @Angew 和 Vlad - 你说得对;虽然这个类是非 POD,但它仍然是由[class]#7 指定的 standard-layout
【解决方案2】:

正如所说的,它是一个转换运算符,将Vector 类型的对象转换为float * 类型的对象。这个转换运算符可以被隐式调用,因为它没有函数说明符explicit。

我认为引入此运算符的想法是将数据成员 x、y、z 作为浮点数组访问。在这种情况下,您可以将一些标准算法应用于类的对象,将其转换为浮点数组。

考虑到第二个重载的运算符函数应该有限定符 const。

考虑下面的代码

#include <iostream>
#include <algorithm>


class Vector
{
public:
    float x,y,z;



    Vector() : x(0), y(0), z(0){
    }

    Vector( float x, float y, float z ) : x(x), y(y), z(z){
    }

    operator float*(){
        return &x;
    }

    operator const float *() const {
        return &x;
    }
};

int main() 
{
    Vector v( 1, 3, 2 );
    auto max = std::max_element( v + 0, v + 3 );
    std::cout << *max << std::endl;

    return 0;
}

输出为 3。

考虑到根据 C++ 标准

具有相同访问权限的(非联合)类的 13 个非静态数据成员 分配控制权(第 11 条)以便 后来的成员拥有更高的 类对象中的地址

所以定义了类的数据成员的顺序。

【讨论】:

    【解决方案3】:

    这是一个转换运算符,允许将类与需要 float* 的 API 一起使用。您有两个不同的版本,因为一个会将类转换为 const float*,而另一个将转换为非 const。但是,非常量转换运算符会破坏您的类的封装。

    有用性:正如我所提到的,当您想要使用需要特定类型的库时,它会非常方便。当两种类型之间存在自然转换时,它也很有用。

    【讨论】:

    • @Angew 感谢 pointer :) 显然,当我指出封装损坏时,我知道这一点,但我的回答不清楚。我已经更新了。
    猜你喜欢
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 2017-10-26
    • 2012-10-03
    • 2011-08-19
    • 2010-09-14
    • 2013-08-19
    相关资源
    最近更新 更多