以下是代码
#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 ++允许参数访问类外的私有数据?这是某种特殊情况吗?
谢谢。
答案 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 ::。 为了允许这些操作符访问对象的私有数据,它们被声明为类声明中类的朋友。通过声明函数或类成为我自己班级的朋友,我表明我相信他们不会篡改我班级的私人数据。