【问题标题】:C++ typecasting vs implicit constructorC++ 类型转换与隐式构造函数
【发布时间】:2011-06-01 21:28:06
【问题描述】:

我正在实现一个代表分数的 c++ 类。这是我的代码。

class Fraction
{
    public:
        Fraction(char i);
        Fraction(int i);
        Fraction(short i);
        Fraction(long int l);
#ifdef __LP64__
        Fraction(long long l);
#endif
        Fraction(float f);
        Fraction(double d);
        Fraction(double x, double y);

        Fraction operator +() const;
        Fraction operator -() const;

        Fraction& operator +=(const Fraction& other);
        Fraction& operator -=(const Fraction& other);
        Fraction& operator *=(const Fraction& other);
        Fraction& operator /=(const Fraction& other);

        bool operator ==(const Fraction& other);
        bool operator !=(const Fraction& other);
        bool operator  >(const Fraction& other);
        bool operator  <(const Fraction& other);
        bool operator >=(const Fraction& other);
        bool operator <=(const Fraction& other);

        operator double();
        operator float();

        static void commonize(Fraction& a, Fraction& b);
        void shorten();

        double getNumerator();
        double getDenominator();

        friend Fraction operator +(Fraction const& a, Fraction const& b);
        friend Fraction operator -(Fraction const& a, Fraction const& b);
        friend Fraction operator *(Fraction const& a, Fraction const& b);
        friend Fraction operator /(Fraction const& a, Fraction const& b);
        friend ostream& operator <<( ostream& o, const Fraction f);

    protected:
        double numerator, denominator;

};

我现在有两个小问题。 现在正在尝试调用

Fraction a(1, 2);
cout << (3 + a) << endl;

只会导致这个错误:

fractiontest.cpp:26: error: ambiguous overload for ‘operator+’ in ‘3 + a’
fractiontest.cpp:26: note: candidates are: operator+(int, double) <built-in>
fractiontest.cpp:26: note:                 operator+(int, float) <built-in>

我真正想要的是这个:

explicit operator double();
explicit operator float();

但显然,这行不通。如果我使用强制转换符号,我希望调用这两个强制转换运算符。例如Fraction f(1, 2); double d = (double)(f);

【问题讨论】:

  • 如 Meyers 在“更有效的 C++”中所述,您应该三思而后行重载强制转换运算符(以及具有非显式单参数构造函数)。
  • 谢谢奥利。我知道有非显式单参数(又名转换)构造函数的问题。我想我应该再考虑一下转换运算符。而且我猜你不能重载int::int(Fraction f),因为 int 是一个原始类型......
  • 你真的需要char、short和float的构造函数吗?
  • @Roland:嗯,很好……float 是的。其他的并不是真正必要的,它们只是为了完整性;)感谢您指出。
  • 所有这些构造函数都是糟糕的设计。只要有一个需要一个或两个double's,并让调用者在必要时进行转换。它与完整性无关,因为您未能允许从可以转换为 double 或 float 的 UDT 构建您的类。这很好:将任何类型转换为双精度不是您班级的责任,而是像分数一样行事。另外,为什么分数组件有浮点数?它们不应该是整数吗? tl;dr:选择一种类型(或模板化你的类)并抛弃其他类型。

标签: c++ casting type-conversion implicit-conversion


【解决方案1】:

根据定义,转换运算符是隐式。你不能让他们明确。

正常的解决方案是命名成员函数来做转换。我认为您还可以创建一个看起来像 static_cast 的专用模板方法并调用显式类方法。

【讨论】:

  • 查看我对关于显式转换运算符的回答的评论,我目前正在搜索 C++0x FDIS。
  • 谢谢,马克。因此,“自动投射”似乎是不可能的。成员函数没问题,我知道 static_cast 是什么……但你能告诉我你所说的 static_cast-method 是什么意思吗?
【解决方案2】:

删除转换运算符,3 + a 应该使用您的朋友 operator+,同时通过隐式构造函数 Fraction(int i); 将 3 隐式转换为 Fraction。


编辑:在显式转换运算符的情况下,C++0x 特别允许这样做:

12.3.2 [class.conv.fct] p2
转换函数可能是显式的,在这种情况下,它只被视为用户定义的直接初始化转换。

C++03 标准没有特别提到这一点。

【讨论】:

  • 感谢您的快速响应。这和我以前的一样有效。但是当我现在想将它“转换”成双精度时,唯一的方法就是创建一个这样做的成员函数,对吗?这意味着它不是自动的......
  • 或者更好的是,定义operator+(int, const Fraction &amp;),并消除同样令人讨厌的隐式构造函数!
  • @Atmo:是的,要么是那个,要么是 explicit operator 手动转换:3 + (int)a;。成员函数通常是首选,因为隐式转换可能非常恶毒。
  • @Oli:我认为为类使用隐式构造函数是非常好的,因为其他任何事情都会导致大量代码重复恕我直言。
  • @Xeo:我同意代码重复点(尽管这可以通过定义operator+(int, const Fraction &amp;) 来解决,例如operator+(const Fraction &amp;, const Fraction &amp;))。但正是这类类是隐式构造函数为何不好的典型示例,因为它们增加了静默引入难以发现的基于拼写错误的方法的数量。
猜你喜欢
  • 2011-09-18
  • 2013-11-02
  • 2019-05-14
  • 1970-01-01
  • 2014-02-24
  • 2016-02-22
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多