【问题标题】:C++ overloaded functions and implicit castsC++ 重载函数和隐式转换
【发布时间】:2026-02-13 06:35:02
【问题描述】:

我有一些可以正常工作的代码,但我想确保它在 C++ 标准下始终可以正常工作。

我创建了两种隐式转换为双精度的类型,并为每种类型创建了一个 sin() 函数。我对其进行了测试,并调用了正确的 sin() 重载,但是否保证编译器不会决定将对象实例隐式转换为 double 并调用 math.h 函数?

此外,我的类和 sin() 重载是否在命名空间中是否重要?如果我将其中任何一个模板化,这有关系吗?

struct AngleDegrees;
struct AngleRadians;

inline double degs2Rads(double degs) { return degs * PI / 180.0; }
inline double rads2Degs(double degs) { return degs * 180.0 / PI; }

struct AngleDegrees
{
private:
    double m_val;

public:
    explicit AngleDegrees(double val) : m_val(val) { }
    explicit AngleDegrees(const AngleRadians& rads);

    operator double() const { return m_val; }
};

struct AngleRadians
{
private:
    double m_val;

public:
    explicit AngleRadians(double val) : m_val(val) { }
    explicit AngleRadians(const AngleDegrees& degs);

    operator double() const { return m_val; }
};

inline AngleDegrees::AngleDegrees(const AngleRadians& rads)
{
    m_val = rads2Degs(rads);
}

inline AngleRadians::AngleRadians(const AngleDegrees& degs)
{
    m_val = degs2Rads(degs);
}

inline double sin(const AngleDegrees& degs)
{
    std::cout << "called sin(AngleDegrees)\n";
    AngleRadians rads(degs);
    return sin((double)rads);
}

inline double sin(const AngleRadians& rads)
{
    std::cout << "called sin(AngleRadians)\n";
    return sin((double)rads);
}

【问题讨论】:

  • 可以进行转换函数explicit
  • ...然后有人偶然打电话给cos并掉进了陷阱。恕我直言,虽然了解隐式转换的规则很重要,但应该避免需要这些知识的设计。
  • 编译器永远不会决定强制转换任何东西。 cast 是您在源代码中编写的内容,用于告诉编译器将一个值convert 转换为另一种类型。

标签: c++ implicit-conversion overload-resolution


【解决方案1】:

我会删除隐式转换并改用成员函数。当然,这些类的原因是为了避免变量可能在一个单元或另一个单元中的问题?

看一下 Ogre 框架,例如: http://www.ogre3d.org/docs/api/html/classOgre_1_1Radian.html http://www.ogre3d.org/docs/api/html/classOgre_1_1Degree.html

至于函数的命名空间,看看ADL:http://en.wikipedia.org/wiki/Argument-dependent_name_lookup你可以把类和sin函数放在同一个命名空间中。

【讨论】:

    【解决方案2】:

    与使用转换为 double 相比,特定的重载将是更好的匹配(如果不需要添加 const 则为精确匹配),因此将调用正确的版本。

    也就是说,将代码放在命名空间中,让 ADR 找到正确的函数以避免任何可能的混淆。

    编辑:您可以考虑使用 boost units 框架来帮助您,而不是自己编写代码。

    【讨论】: