2

我最近一直在做一个分数类,重载运算符时我没有得到预期的结果,我不知道为什么。希望有人可以帮助阐明一些光。我试图只包含相关代码。

const fraction fraction::operator* (fraction frac)
{
    return fraction(frac.numerator * numerator, frac.denominator * denominator);
}

const fraction fraction::operator* (int num)
{
    return fraction(numerator*num, denominator);
}

fraction& fraction::operator= (const fraction &rightSide)
{
    return *this;
}

这些操作是我发现工作正常的操作(其中 frac# 是一个分数对象):

frac1 = frac2;
frac3 = frac4 * 2;
frac5 = frac6 * frac7;

上述操作按预期工作,但以下操作使 frac8 与初始化时一样:

fraction frac8(4, 5); // Initializes a fraction, setting numerator = 4, denominator = 5
frac8 = frac8 * 3; // This doesn't quite work, leaving frac8 with the original numerator/denominator

我只是不明白为什么 frac3 = frac4 * 2 有效,但 frac8 = frac8 * 3 无效。有任何想法吗?在赋值运算符中使用 const 关键字我发现不是解决方案。

4

3 回答 3

5

如果你只是在它的身体里做任何有用的事情,你怎么期望你operator=做任何有用的事情return *this;?您必须分配给 的字段this的字段rightSide

但是,更重要的是,如果您的类不管理在复制的情况下需要一些特殊处理的资源,您可以使用编译器提供的赋值运算符。它只是将一个实例的字段复制到另一个实例中,对于一个fraction类来说,这似乎非常好。

顺便说一句,通常您使用复合对应物来实现“常规”运算符;您可能想看看运算符重载常见问题解答

于 2012-08-21T22:12:16.553 回答
1

您的任何分配都不起作用,因为您的分配运算符实现是空的,除了返回对其左侧的引用之外什么都不做。

即这三个任务都没有

frac1 = frac2;
frac3 = frac4 * 2;
frac5 = frac6 * frac7;

真的工作。

出于某种原因,您声称上述作业“有效”,但这一定是您的某种困惑。他们不“工作”。也没有frac8 = frac8 * 3,出于同样的原因。

PS我怀疑你的“工作”陈述实际上是这样写的

fraction frac1 = frac2;
fraction frac3 = frac4 * 2;
fraction frac5 = frac6 * frac7;

这可能确实有效。但是这种语法与赋值运算符无关。在这种情况下不使用赋值运算符。此语法对应于复制初始化。它依赖于类的复制构造函数(至少在概念上),而不是赋值运算符。这就是它可能起作用的原因,而真正的分配不起作用,因为您通过将复制分配运算符设为空来“丧失能力”。

于 2012-08-21T22:37:32.797 回答
0

您的赋值运算符仅返回对象本身(即,*this)...所以在您的最后一个示例中,它只是一个无操作,而不是从右侧对象执行实际的赋值操作。换句话说,一个临时fraction对象是由您创建的operator*,但是由于您的赋值运算符不会复制右侧对象的值,因此您最终只是丢弃了方法完成后fraction生成的临时实例。operator*operator=

顺便说一句,在创建用户生成的赋值运算符时,您可能需要研究三规则。它基本上指出,如果您的类具有需要用户生成的赋值运算符的资源,那么您还应该实现用户定义的复制构造函数和析构函数......后两项的编译器生成的默认值不会如果有超出编译器默认实现这些方法的资源需要管理的资源就足够了。

于 2012-08-21T22:12:39.017 回答