1

下面是代码

编码:

#include <iostream>
using namespace std;

class Rational {
  int num;  // numerator
  int den;  // denominator
  friend istream& operator>> (istream & , Rational&);
  friend ostream& operator<< (ostream &  , const Rational&);
 public:
  Rational (int num = 0, int den = 1)
    :     num(num), den(den) {}
  void getUserInput() {
    cout << "num = ";
    cin >> num;
    cout << "den = ";
    cin >> den;
  }
  Rational operator+(const Rational &);
};

Rational Rational::operator+ (const Rational& r) { //HERE 
  int n = num * r.den + den * r.num;
  int d = den * r.den;
  return Rational (n, d);
}

istream& operator>> (istream & is , Rational& r)
{
    is >> r.num >> r.den;
}

ostream& operator<< (ostream & os , const Rational& r)
{
    os << r.num << " / " <<  r.den << endl;;
}
int main() {
  Rational r1, r2, r3;
  cout << "Input r1:\n";
  cin >> r1;
  cout << "Input r2:\n";
  cin >> r2;
  r3 = r1 + r2;
  cout << "r1 = " << r1;
  cout << "r2 = " << r2;
  cout << "r1 + r2 = " << r3;
  return 0;
}

问题

上面的代码有一个 operator+ 重载,在 operator+ 定义中我们可以看到r访问私有数据的参数(r.num 和 r.den)。为什么 C++ 允许参数访问类之外的私有数据?这是某种特殊情况吗?

谢谢你。

4

5 回答 5

3

访问说明符适用于类级别,而不是实例级别,因此该类可以看到任何其他实例Rational的私有数据成员 。Rational由于您Rational operator+是成员函数,因此它可以访问其Rational参数的私有数据。

注意:规范的方法是定义一个成员operator +=,然后用它来实现一个非成员operator+

struct Foo
{
  int i;

  Foo& operator+=(const Foo& rhs) 
  { 
    i += rhs.i;
    return *this;
  }

};

Foo operator+(Foo lhs, const Foo& rhs)
{
  return lhs += rhs;
}
于 2012-09-12T14:26:31.567 回答
1

Rational::operator+是一个成员函数,因此它可以访问每个对象的所有成员。 Rational

编码提示:这种东西通常写成两部分:一个operator+=是成员,一个operator+不是。像这样:

Rational& Rational::operator+=(const Rational& rhs) {
    num = num * rhs.den + den * rhs.num;
    den *= rhs.den;
    return *this;
}

Rational operator+(const Rational& lhs, const Rational& rhs) {
    Rational result(lhs);
    result += rhs;
    return result;
}
于 2012-09-12T14:31:42.623 回答
1

Why C++ allow the parameter to access private data outside of the class ? Is it some kind of a special case?

The rule with access specifiers is:
"Access specifiers apply to per class and not per object"
So, You can always access private members of a class object in member function of that class.

A copy constructor/copy assignment operator are commonly used examples of the rule though we do not notice it that often.

Online Sample:

class Myclass
{
    int i;
    public:
       Myclass(){}
       Myclass(Myclass const &obj3)
       { 
            //Note i is private member but still accessible
            this->i = obj3.i;
       }
};

int main()
{
    Myclass obj;
    Myclass obj2(obj);
}

Good Read:
What are access specifiers? Should I inherit with private, protected or public?

于 2012-09-12T14:29:05.380 回答
1

虽然其他张贴者已经解释了 C++ 访问说明符是如何工作的,但没有人解释它们为什么以这种方式工作。

增加封装是为了尽量减少可以访问您的对象内部(即您的数据成员)的代码量,而不是对象的数量。如果访问说明符限制对同一类中其他对象内部的访问,这不会增加封装。

封装很重要,因为它意味着更改实现细节将影响最少的代码。增加封装会增加代码的可维护性。这是一个构建时的概念,而不是运行时的概念。

于 2013-01-13T15:28:59.087 回答
1

这个问题揭示了一个误解:“为什么 C++ 允许参数访问类之外的私有数据?”

方法 operator+ 确实属于该类:它在类中声明,在其实现中,您将看到该方法是该类的成员,前缀为 class_name:: 因此,对于 operator+,如果私有成员以外的成员,则无法访问班上。

运算符 << 和 >> 是不同的情况——它们实际上不属于该类,因为它们是由流对象调用的。这就是为什么他们的实现没有前缀 Rational::。为了允许这些操作员访问对象的私有数据,他们在类声明中被声明为类的朋友。通过将函数或类声明为我自己的类的朋友,我表明我相信它们不会篡改我类的私有数据。

于 2014-06-28T05:54:03.247 回答