【c++ primer, 5e】访问控制与封装

练习

7.16

无,类的接口定义在public说明符之后,类的实现细节定义在private说明符之后。

7.17

有。类成员的默认访问权限不同。class的类成员默认为private,struct的则默认为public。

通常来说,当我们希望定义的类的所有成员是public的时候就用struct。

7.18

p242

7.19

【友元】

练习

7.20

声明的类外函数需要直接引用类内的私有成员的时候要用到友元函数。

设计原因:并非所有的、与某个类相关的函数都适合声明成那个类的成员函数,例如书上的add(obj, obj);

利弊:不详。。。

7.21

遇到问题了。已经声明成友元函数还是不能访问私有数据???

#include <iostream>
#include <string>
using namespace std;

// Sales_data.h
class Sales_data {
friend Sales_data add(const Sales_data&, const Sales_data&);
friend ostream &print(ostream&, const Sales_data&);
friend istream &read(iostream&, Sales_data&);
public:
    Sales_data() = default; 
    Sales_data(const string &s): bookNo(s) {} 
    Sales_data(const string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) {}
    Sales_data(istream&);
    std::string isbn() const { return bookNo; } 
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
private:
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};
// Sales_data的非成员接口函数
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);
istream &read(iostream&, Sales_data&);

// Sales_data.cpp
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}
istream &read(istream &is, Sales_data &item)
{
    double price = 0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}
double Sales_data::avg_price() const {
    if (units_sold)
        return revenue/units_sold;
    else
        return 0;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
    Sales_data sum = lhs;
    sum.combine(rhs);
    return sum;
}
Sales_data::Sales_data(istream &is)
{
    read(is, *this);
}


// main.cpp
int main()
{
    Sales_data data1; // default
    Sales_data data2("ISOD233");
    Sales_data data3("ISOD233", 3, 22.5);
    Sales_data data4(cin);
    
    print(cout, data1) << endl;
    print(cout, data2) << endl;
    print(cout, data3) << endl;
    print(cout, data4) << endl;
    /* output:
    0 0
    ISOD233 0 0 0
    ISOD233 3 67.5 22.5
    DASD23 4 88 22
    */
    return 0;
}

编译结果如下:

$ g++ prog1.cpp -std=c++11
prog1.cpp: In function 'std::istream& read(std::istream&, Sales_data&)':
prog1.cpp:19:12: error: 'std::__cxx11::string Sales_data::bookNo' is private
     string bookNo;
            ^
prog1.cpp:38:16: error: within this context
     is >> item.bookNo >> item.units_sold >> price;
                ^
prog1.cpp:20:27: error: 'unsigned int Sales_data::units_sold' is private
     unsigned units_sold = 0;
                           ^
prog1.cpp:38:31: error: within this context
     is >> item.bookNo >> item.units_sold >> price;
                               ^
prog1.cpp:21:22: error: 'double Sales_data::revenue' is private
     double revenue = 0.0;
                      ^
prog1.cpp:39:10: error: within this context
     item.revenue = price * item.units_sold;
          ^
prog1.cpp:20:27: error: 'unsigned int Sales_data::units_sold' is private
     unsigned units_sold = 0;
                           ^
prog1.cpp:39:33: error: within this context
     item.revenue = price * item.units_sold;

 已改正:

#include <iostream>
#include <string>
using namespace std;

// Sales_data.h
class Sales_data {
friend Sales_data add(const Sales_data&, const Sales_data&);
friend ostream &print(ostream&, const Sales_data&);
friend istream &read(istream&, Sales_data&);
public:
    Sales_data() = default; 
    Sales_data(const string &s): bookNo(s) {} 
    Sales_data(const string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) {}
    Sales_data(istream&);
    std::string isbn() const { return bookNo; } 
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
private:
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};
// Sales_data的非成员接口函数
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);
istream &read(istream&, Sales_data&);

// Sales_data.cpp
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}
istream &read(istream &is, Sales_data &item)
{
    double price = 0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}
double Sales_data::avg_price() const {
    if (units_sold)
        return revenue/units_sold;
    else
        return 0;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
    Sales_data sum = lhs;
    sum.combine(rhs);
    return sum;
}
Sales_data::Sales_data(istream &is)
{
    read(is, *this);
}


// main.cpp
int main()
{
    Sales_data data1; // default
    Sales_data data2("ISOD233");
    Sales_data data3("ISOD233", 3, 22.5);
    Sales_data data4(cin);
    
    print(cout, data1) << endl;
    print(cout, data2) << endl;
    print(cout, data3) << endl;
    print(cout, data4) << endl;
    /* output:
    0 0
    ISOD233 0 0 0
    ISOD233 3 67.5 22.5
    DASD23 4 88 22
    */
    return 0;
}

声明多写了一个o。

7.22

#include <iostream>
#include <string>
using namespace std;

// Person.h
class Person {
friend istream &read(istream &is, Person &p);
public:
    Person() = default;
    Person(const string &name): name(name) {}
    Person(const string &name, const string &address): name(name), address(address) {}
    Person(istream&);
    string getName() const { return name; }
    string getAddress() const  { return address; }
private:
    string name;
    string address;
};
istream &read(istream&, Person&);
ostream &print(ostream&, const Person&);

// Person.cpp
istream &read(istream &is, Person &p)
{
    is >> p.name >> p.address;
    return is;
}
ostream &print(ostream &os, const Person &p)
{
    os << p.getName() << " " << p.getAddress();
    return os;
}
Person::Person(istream &is)
{
    read(is, *this);
}

// main.cpp
int main()
{
    Person p1;
    Person p2("xklf");
    Person p3("llyy", "china");
    Person p4(cin);
    print(cout, p1) << endl;
    print(cout, p2) << endl;
    print(cout, p3) << endl;
    print(cout, p4) << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/xkxf/p/6687421.html