7

作为我的计算机软件开发学位的一部分,我的一个实验室包括创建一个计算器类模板和一个分数类。

问题出在我的分数课上。我现在的任务是重载加号运算符以允许将两个分数相加。

分数.cpp:

#include "Fraction.h"

const Fraction Fraction::operator+ (const Fraction &rhs) const
{
    return Fraction(_num * rhs.GetDen() + (rhs.GetNum() * _den), _den * rhs.GetDen());
}

分数.h

#pragma once

class Fraction
{
    public:
        Fraction(const int &num, const int &den) : _num(num), _den(den) {}
        ~Fraction(void) {}
        const int GetNum(void) { return _num; }
        const int GetDen(void) { return _den; }
        const Fraction operator+ (const Fraction &rhs) const;

    private:
        const int _num, _den;
};

Visual Studio 抱怨我的分数访问器无法“将此指针从 const 分数转换为分数 &”。我完全感到困惑。

4

5 回答 5

12

您还需要将访问器限定为 const:

int GetNum(void) const { return _num; }

顺便说一句,将返回类型限定为 const int 并没有真正意义,无论如何它将是一个 int 。您的编译器应该发出警告。

于 2011-05-11T18:44:47.963 回答
1

您的 GetNum 和 GetDen 访问器方法未声明为“const”,因此不能在 operator+ 中针对 const Fractions 调用它们。

于 2011-05-11T18:45:32.740 回答
1

第一个问题,你为什么让函数首先返回一个“const Fraction”?这对您的代码的使用方式施加了任意限制。很明显,您的 Fraction 类基本上已经是隐式的 const。没有必要这样做。

但是,您的成员函数是非常量的。也就是说,它们不会告诉编译器您不会尝试更改类本身的状态。对于所有不改变状态的成员函数,请在成员函数声明的末尾加上关键字“const”。

于 2011-05-11T18:45:43.867 回答
1

你的吸气剂不是常量:

    int GetNum() const { return _num; }
    int GetDen() const { return _den; }
         ///    ^^^^^^^^

您实际上并不需要这些吸气剂。我个人会把它们扔掉。
注意:一个类是它自己的朋友,因此可以访问另一个实例的成员。

const Fraction Fraction::operator+ (const Fraction &rhs) const
{
    return Fraction(_num * rhs._den+ (rhs._num * _den), _den * rhs._den);
}

其他注意事项:

  • 将 void 设置为参数也不是一个好主意(这是 C 风格)。
  • const int 真的没有意义,只是让它返回 int。
  • 请不要使用下划线作为第一个字符。它是合法的,但是如果您不小心并且不了解有关下划线的所有规则,则很容易出错。
于 2011-05-11T18:46:19.490 回答
1
const int GetDen(void) { return _den; }

应该(或可能)是

int GetDen(void) const { return _den; }

第一个返回一个 const 副本。复制返回意味着将生成副本并将其作为临时对象提供给调用者函数,因此是 const(“只读”)对象。因此,按副本返回会使副本成为只读的。

第二个使您的函数即使 Fraction 对象是 const 也是可调用的 - 它是一个“只读”可访问函数(您可能会说)。这可能是你想写的,如果不是,那也比没有 const 好。

顺便说一句,参数中的 void 在 C++ 中没有用,你可以避免输入它,直接说int GetNum() const{ return _num; }

另一个细节:以下划线字符开头的名称由标准保留用于标准实现。使用它们并不是很危险,但你永远不知道。如果要保留它们,至少将所有代码封装在命名空间中。

于 2011-05-11T18:49:35.057 回答