2017-09-28 31 views
1

我试图超载时遇到问题operator float()operator float() const。我认为我可以使用两种重载为“做事情”和“只读”提供不同的版本......但事实证明,使用包含这些重载的类的静态实例我不能。带有静态成员的运算符float()和float()const的隐式转换

归结问题几乎减少到这一点:

// Does some math and should convert to float 
struct ToFloat 
{ 
    // float conversion here 
    operator float() 
    { 
    cout << "called operator float() of " << s << "\n"; 
    f += 1.0f; 
    return f; 
    } 

    // just get current value here 
    operator float() const 
    { 
    cout << "called operator float() *const* of " << s << "\n"; 
    return f; 
    } 

    float f; 
    std::string s; 
}; 

// Uses a static and a normal member of ToFloat 
struct Container 
{ 
    // return both instances (with some more math before) 
    operator float() 
    { 
    return s * m; 
    } 

    // just provide read access 
    operator float() const 
    { 
    return s * m; 
    } 

    static inline ToFloat s { 1.0f, "static" }; 
    ToFloat m { 1.0f, "member" }; 
}; 

// Uses the container, but must also provide read-only access 
struct Use 
{ 
    // Give me operator float() of my container 
    float get() 
    { 
    return c; 
    } 

    // Give me operator float() const of my container 
    float getC() const 
    { 
    return c; 
    } 

    Container c {}; 
}; 

int main() 
{ 
    Use u {}; 

    printf("getC() %f \n\n", u.getC()); 
    printf("get() %f \n\n", u.get()); 
    printf("getC() %f \n\n", u.getC()); 
} 

将会产生以下输出...

called operator float() of static 
called operator float() *const* of member 
getC() 2.000000 

called operator float() of static 
called operator float() of member 
get() 6.000000 

called operator float() of static 
called operator float() *const* of member 
getC() 8.000000 

我真的不明白为什么ToFloat静态实例总是使用非const转换,即使从一个函数中调用const?这里适用什么规则?

+2

静态成员不'const'只是因为类的一个实例是'const'。它也不会从那个实例的代码中作为const出现。不相关的,但使用'float'而不是默认'double'通常只是愚蠢的警告的邀请,而维护者浪费时间试图弄清楚为什么你会这么做。 –

+0

我的目标平台不支持双硬件。 – Vinci

+0

@ Cheersandhth.-Alf关于'float'与'double':真的吗?我想说的是,在大量的数字处理代码中,很多人认为'double'的精度值得速度和内存成本。 – Angew

回答

1

静态数据成员Container::s只是简单的ToFloat类型。它总是直接访问,从来没有通过隐含的取消引用this。换句话说,容器的const运营商有效的是这样的:

operator float() const 
{ 
    return Container::s * this->m; 
} 

由此看来,它应该是显而易见的,我们没有理由为Container::sconst被视为仅仅因为thisconst Container *。如果你希望它被视为const,你必须明确地限定它:

operator float() const 
{ 
    return std::as_const(s) * m; 
}