运算符重载中的类数据封装(私有数据)

时间:2012-09-12 14:25:17

标签: c++ operator-overloading encapsulation

以下是代码

守则:

#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 ++允许参数访问类外的私有数据?这是某种特殊情况吗?

谢谢。

5 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:1)

  

为什么C ++允许参数访问类外的私有数据?这是某种特殊情况吗?

具有访问说明符的规则是:
“访问说明符适用于每个类而非每个对象”
因此,您始终可以在该类的成员函数中访问类对象的private个成员。

复制构造函数/复制赋值运算符是规则的常用示例,尽管我们通常不会注意到它。

<强> 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);
}

好读:
What are access specifiers? Should I inherit with private, protected or public?

答案 2 :(得分:1)

Rational::operator+是会员功能,因此可以访问 Rational个对象的所有成员。

编码提示:这类事情通常分为两部分:operator+=是成员,而operator+则不是。{1}}。像这样:

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;
}

答案 3 :(得分:1)

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

增加封装是关于最小化代码量,它可以访问对象内部(即数据成员),而不是对象的数量。如果访问说明符限制访问同一类中其他对象的内部,则会增加封装。

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

答案 4 :(得分:1)

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

方法operator +确实属于类:它在类中声明,在它的实现中你会看到该方法是前缀class_name ::的类成员 因此,对于运营商+,如果班级以外的私人成员则无法访问。

运营商&lt;&lt;和&gt;&gt;是一个不同的情况 - 这些实际上不属于类,因为它们由流对象调用。这就是为什么他们的实现没有前缀Rational ::。 为了允许这些操作符访问对象的私有数据,它们被声明为类声明中类的朋友。通过声明函数或类成为我自己班级的朋友,我表明我相信他们不会篡改我班级的私人数据。