第七章 類 __C++Primer第五版

類.png
定義抽象數(shù)據(jù)類型
7.1 練習(xí)
#include <iostream>
#include <string>
using namespace std;
//struct 和 class 的唯一區(qū)別是默認(rèn)的訪問權(quán)限。
//struct默認(rèn)是public
//class默認(rèn)是private
struct Sales_data
{
string bookNo; //編號(hào)
unsigned units_sold = 0; //賣出的數(shù)量, 類初始化,C++新標(biāo)準(zhǔn),vs2010不支持
double revenue = 0; //總金額
};
int main()
{
Sales_data total;
if (cin >> total.bookNo >> total.units_sold >> total.revenue)
{
Sales_data trans;
while(cin >> trans.bookNo >> trans.units_sold >> trans.revenue)
{
if (trans.bookNo == total.bookNo)
{
total.units_sold += trans.units_sold;
total.revenue += trans.revenue;
}
else
{
cout << total.bookNo << "\t" << total.units_sold << "\t" << total.revenue << endl;
total = trans;
}
}
cout << total.bookNo << "\t" << total.units_sold << "\t" << total.revenue << endl;
}
else
{
cerr << "No data?" << endl;
return -1; //表示失敗
}
return 0;
}
定義改進(jìn)的Sales_data類
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <iostream>
#include <string>
struct Sales_data
{
//成員函數(shù)
//獲得isbn編號(hào)
std::string isbn() const //const成員函數(shù)
{
return this->bookNo;
}
Sales_data& combine(const Sales_data&);
double avg_price() const; //const成員函數(shù)
//數(shù)據(jù)成員
std::string bookNo;
unsigned units_sole;
double revenue;
};
//非成員函數(shù)
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream& print(std::ostream&, const Sales_data&);
std::istream& read(std::istream&, Sales_data&);
//對(duì)未定義的成員函數(shù)在類外進(jìn)行定義
double Sales_data::avg_price() const
{
if (units_sold)
{
return revenue/units_sold;
}
else
{
return 0;
}
}
//定義一個(gè)返回this對(duì)象的函數(shù)
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
this->units_sold += rhs.units_sold;
this->revenue += rhs.revenue;
return *this; //返回調(diào)用該函數(shù)的對(duì)象
}
//對(duì)非成員函數(shù)定義
std::istream& read(std::istream &is, Sales_data &item)
{
double price = 0;
//輸入isbn編號(hào), 賣出數(shù)量, 單價(jià)
is >> item.bookNo >> item.units_sold >> price;
item.revenue = item.units_sold * price;
return is;
}
std::ostream& print(std::ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
//把lhs的數(shù)據(jù)成員拷貝給sum
//默認(rèn)情況下,拷貝類的對(duì)象其實(shí)拷貝的是對(duì)象的數(shù)據(jù)成員
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
#endif
引入const成員函數(shù)
上面Sales_data類中的isbn()和avg_price()函數(shù)都是常量成員函數(shù)。緊跟在參數(shù)列表后面的const表示this是一個(gè)指向常量的常量指針也就是const Sales_data const *類型,如果沒有列表后面的const,this的類型是Sales_data const *類型。
常量對(duì)象以及常量對(duì)象的引用或指針都只能調(diào)用常量成員函數(shù)。
7.3 7.7練習(xí)題
#include <iostream>
#include <string>
#include "Sales_data.h"
using namespace std;
int main()
{
Sales_data total;
if (read(cin, total))
{
Sales_data trans;
while(read(cin, trans))
{
if (trans.isbn() == total.isbn())
{
total.combine(trans);
}
else
{
print(cout, total);
total = trans;
}
}
print(cout, total);
}
else
{
cout << "No Data?" << endl;
return -1;
}
return 0;
}
7.4 7.5 7.9練習(xí)
編寫一個(gè)名為Person的類,使其表示人員的姓名和住址。使用string對(duì)象存放這些元素,接下來的練習(xí)將不斷充實(shí)這個(gè)類的其他特征。
#ifndef PERSON_H
#define PERSON_H
#include <iostream>
#include <string>
struct Person
{
//數(shù)據(jù)成員
std::string name;
std::string address;
//成員函數(shù)
//返回name
std::string getName() const
{
return this->name;
}
//返回address
std::string getAddress() const{
return this->address;
}
};
std::ostream& print(std::ostream &os, const Person &p)
{
os << p.getName() << "的地址是" << person.getAddress() << endl;
return os;
}
std::istream& read(std::istream &is, Person &p)
{
is >> p.name >> p.address;
return is;
}
#endif
//練習(xí)7.5的 main.cpp
#include <iostream>
#include <string>
#include "Person.h"
using namespace std;
int main()
{
Person person;
//person.name = "MangoLee";
//person.address = "Beijing";
cin >> person.name >> person.address;
cout << person.getName() << "的地址是" << person.getAddress() << endl;
system("pause");
return 0;
}
//練習(xí)7.9的main.cpp
int main()
{
Person person;
read(cin, person);
print(cout, person);
system("pause");
return 0;
}
構(gòu)造函數(shù)
默認(rèn)構(gòu)造函數(shù)
默認(rèn)構(gòu)造函數(shù)按照如下規(guī)則初始化類的數(shù)據(jù)成員:
如果存在類內(nèi)的初始值,用它來初始化成員(C++11)
struct Person { string name = 'mango'; //類內(nèi)初始化,vs2010不支持此C++11新特性 int age = 26; //類內(nèi)初始化,vs2010不支持此C++11新特性 }-
否則,默認(rèn)初始化該成員
- 如果是內(nèi)置類型,定義于任何函數(shù)體之外的變量被初始化為0;定義在函數(shù)體內(nèi)部的不被初始化
- 每個(gè)類調(diào)用默認(rèn)初始化
7.11-1.13 練習(xí)
為Sales_data添加構(gòu)造函數(shù),并用istream構(gòu)造函數(shù)重寫229頁程序。
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <iostream>
#include <string>
struct Sales_data
{
//構(gòu)造函數(shù)
Sales_data();
Sales_data(const std::string &str):
bookNo(str),units_sold(0),revenue(0){}
//初始化列表
Sales_data(const std::string &str, unsigned n, double p):
bookNo(str),units_sold(n),revenue(p){}
Sales_data(std::istream &is);
//成員函數(shù)
//獲得isbn編號(hào)
std::string isbn() const
{
return this->bookNo;
}
Sales_data& combine(const Sales_data&);
double avg_price() const;
//數(shù)據(jù)成員
std::string bookNo;
unsigned units_sold;
double revenue;
};
//非成員函數(shù)聲明
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream& print(std::ostream&, const Sales_data&);
std::istream& read(std::istream&, Sales_data&);
Sales_data::Sales_data(std::istream &is)
{
read(is, *this); //*this 代表本身
}
//對(duì)未定義的成員函數(shù)在類外進(jìn)行定義
double Sales_data::avg_price() const
{
if (units_sold)
{
return revenue/units_sold;
}
else
{
return 0;
}
}
//定義一個(gè)返回this對(duì)象的函數(shù)
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
this->units_sold += rhs.units_sold;
this->revenue += rhs.revenue;
return *this; //返回調(diào)用該函數(shù)的對(duì)象
}
//對(duì)非成員函數(shù)定義
std::istream& read(std::istream &is, Sales_data &item)
{
double price = 0;
//輸入isbn編號(hào), 賣出數(shù)量, 單價(jià)
is >> item.bookNo >> item.units_sold >> price;
item.revenue = item.units_sold * price;
return is;
}
std::ostream& print(std::ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
//把lhs的數(shù)據(jù)成員拷貝給sum
//默認(rèn)情況下,拷貝類的對(duì)象其實(shí)拷貝的是對(duì)象的數(shù)據(jù)成員
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
#endif
訪問控制和封裝
引入public 和private的關(guān)鍵詞。
//Sales.data.h添加訪問控制,函數(shù)實(shí)現(xiàn)不變。
class Sales_data
{
public:
Sales_data();
Sales_data(const std::string &str):
bookNo(str),units_sold(0),revenue(0){}
Sales_data(const std::string &str, unsigned n, double p):
bookNo(str),units_sold(n),revenue(p){}
Sales_data(std::istream &is);
std::string isbn() const{return this->bookNo;}
Sales_data& combine(const Sales_data&);
private:
double avg_price() const;
std::string bookNo;
unsigned units_sold;
double revenue;
};
友元
類可以允許友元類和友元函數(shù)訪問它的私有成員。
//Sales.data.h添加友元函數(shù)
class Sales_data
{
//友元聲明,不代表普通聲明,函數(shù)需要聲明仍需要在類外進(jìn)行聲明
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::ostream& print(std::ostream&, const Sales_data&);
friend std::istream& read(std::istream&, Sales_data&);
public:
Sales_data();
Sales_data(const std::string &str):
bookNo(str),units_sold(0),revenue(0){}
Sales_data(const std::string &str, unsigned n, double p):
bookNo(str),units_sold(n),revenue(p){}
Sales_data(std::istream &is);
std::string isbn() const{return this->bookNo;}
Sales_data& combine(const Sales_data&);
private:
double avg_price() const;
std::string bookNo;
unsigned units_sold;
double revenue;
};
//非成員函數(shù)聲明
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream& print(std::ostream&, const Sales_data&);
std::istream& read(std::istream&, Sales_data&);
7.22 練習(xí)
class Person
{
private:
std::string name;
std::string address;
public:
std::string getName() const
{
return this->name;
}
std::string getAddress() const{
return this->address;
}
};