第七章 类 __C++Primer第五版
定义抽象数据类型
7.1 练习
#include
#include
using namespace std;
//struct 和 class 的唯一区别是默认的访问权限。
//struct默认是public
//class默认是private
struct Sales_data
{
string bookNo; //编号
unsigned units_sold = 0; //卖出的数量, 类初始化,C++新标准,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;
}
定义改进的Sales_data类
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include
#include
struct Sales_data
{
//成员函数
//获得isbn编号
std::string isbn() const //const成员函数
{
return this->bookNo;
}
Sales_data& combine(const Sales_data&);
double avg_price() const; //const成员函数
//数据成员
std::string bookNo;
unsigned units_sole;
double revenue;
};
//非成员函数
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream& print(std::ostream&, const Sales_data&);
std::istream& read(std::istream&, Sales_data&);
//对未定义的成员函数在类外进行定义
double Sales_data::avg_price() const
{
if (units_sold)
{
return revenue/units_sold;
}
else
{
return 0;
}
}
//定义一个返回this对象的函数
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
this->units_sold += rhs.units_sold;
this->revenue += rhs.revenue;
return *this; //返回调用该函数的对象
}
//对非成员函数定义
std::istream& read(std::istream &is, Sales_data &item)
{
double price = 0;
//输入isbn编号, 卖出数量, 单价
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的数据成员拷贝给sum
//默认情况下,拷贝类的对象其实拷贝的是对象的数据成员
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
#endif
引入const成员函数
上面Sales_data类中的isbn()
和avg_price()
函数都是常量成员函数。紧跟在参数列表后面的const表示this是一个指向常量的常量指针也就是const Sales_data const *
类型,如果没有列表后面的const,this的类型是Sales_data const *
类型。
常量对象以及常量对象的引用或指针都只能调用常量成员函数。
7.3 7.7练习题
#include
#include
#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练习
编写一个名为Person的类,使其表示人员的姓名和住址。使用string对象存放这些元素,接下来的练习将不断充实这个类的其他特征。
#ifndef PERSON_H
#define PERSON_H
#include
#include
struct Person
{
//数据成员
std::string name;
std::string address;
//成员函数
//返回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
//练习7.5的 main.cpp
#include
#include
#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;
}
//练习7.9的main.cpp
int main()
{
Person person;
read(cin, person);
print(cout, person);
system("pause");
return 0;
}
构造函数
默认构造函数
默认构造函数按照如下规则初始化类的数据成员:
如果存在类内的初始值,用它来初始化成员(C++11)
struct Person { string name = 'mango'; //类内初始化,vs2010不支持此C++11新特性 int age = 26; //类内初始化,vs2010不支持此C++11新特性 }
-
否则,默认初始化该成员
- 如果是内置类型,定义于任何函数体之外的变量被初始化为0;定义在函数体内部的不被初始化
- 每个类调用默认初始化
7.11-1.13 练习
为Sales_data添加构造函数,并用istream构造函数重写229页程序。
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include
#include
struct Sales_data
{
//构造函数
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);
//成员函数
//获得isbn编号
std::string isbn() const
{
return this->bookNo;
}
Sales_data& combine(const Sales_data&);
double avg_price() const;
//数据成员
std::string bookNo;
unsigned units_sold;
double revenue;
};
//非成员函数声明
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 代表本身
}
//对未定义的成员函数在类外进行定义
double Sales_data::avg_price() const
{
if (units_sold)
{
return revenue/units_sold;
}
else
{
return 0;
}
}
//定义一个返回this对象的函数
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
this->units_sold += rhs.units_sold;
this->revenue += rhs.revenue;
return *this; //返回调用该函数的对象
}
//对非成员函数定义
std::istream& read(std::istream &is, Sales_data &item)
{
double price = 0;
//输入isbn编号, 卖出数量, 单价
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的数据成员拷贝给sum
//默认情况下,拷贝类的对象其实拷贝的是对象的数据成员
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
#endif
访问控制和封装
引入public 和private的关键词。
//Sales.data.h添加访问控制,函数实现不变。
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;
};
友元
类可以允许友元类和友元函数访问它的私有成员。
//Sales.data.h添加友元函数
class Sales_data
{
//友元声明,不代表普通声明,函数需要声明仍需要在类外进行声明
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;
};
//非成员函数声明
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 练习
class Person
{
private:
std::string name;
std::string address;
public:
std::string getName() const
{
return this->name;
}
std::string getAddress() const{
return this->address;
}
};