本系列文章主要对C++Primer进行一个复习
前一段时间花了两个月时间把这本数啃了个差不多,一个月过去了,好像忘记了不少,尤其是关于类的部分(因为暂时也用不到)。但眼看着就要面临找实习找工作了,于是想再熟练一边,并通过博客记录,以便今后忘了的时候翻阅。
又因为之前是按顺序看的,看到类那块儿已经精疲力尽了。。。。所以这次换个方式,倒着往前看,也就是先从类看起。话不多说,开始吧。
第七章:类
这一章由一个Sales_data类来引入。先把代码贴上,之后通过每一个函数来提取知识点。
Sales_data.h
#pragma once
#include<iostream>
using namespace std;
struct Sales_data
{
string isbn() const;
Sales_data& combine(const Sales_data&);
double avg_price() const;
string bookNo;
unsigned units_sold = 0; //本书销量
double revenue = 0.0;//总收入
};
//Sales_data的非成员接口函数
//它们是一些辅助函数
istream& read(istream&, Sales_data&);
ostream& print(ostream&, const Sales_data&);
Sales_data add(Sales_data&, Sales_data&);
Sales_data.cpp
#include<iostream>
#include"Sales_data.h"
using namespace std;
string Sales_data::isbn() const
{
return bookNo;
}
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
double Sales_data::avg_price() const
{
return revenue / units_sold;
}
istream& read(istream& in, Sales_data& item)
{
double price = 0;
in >> item.bookNo >> item.units_sold >> price;
item.revenue = item.units_sold * price;
return in;
}
ostream& print(ostream& out, const Sales_data& item)
{
out << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return out;
}
Sales_data add(Sales_data& lhr, Sales_data& rhs)
{
Sales_data sum = lhr; //此时调用拷贝构造函数
sum.combine(rhs);
return sum;
}
run_MySales_Data.cpp
//统计每种数的销售总数和总价值以及平均单价
#include<iostream>
#include"Sales_data.h"
using namespace std;
int main()
{
Sales_data total;
if (read(cin, total))
{
Sales_data trans;
while (read(cin, trans))
{
if (total.isbn() == trans.isbn())
{
total.combine(trans);
}
else
{
print(cout, total) << endl;
total = trans;
}
}
print(cout, total) << endl;
}
else
{
cout << "No data\n";
}
}
1. 注意到在定义类用的是struct,struct与class 唯一的区别 是:struct默认情况下为共有public,而class默认情况下为私有private(C++primer原话)。这也就是为什么在read以及print这些非成员接口函数里面直接通过类访问类的数据成员是可行的。
2. isbn(): 这个函数本身是很简单的,就是一个返回bookNo的成员函数。但是通过这个函数,我们来说一下,为什么调用total.isbn()我们就能返回total的bookNo成员呢?
如果isbn()指向的是Sales_data的成员,则它隐式的指向调用该函数的对象的成员。例如上面的,当isbn()返回bookNO时,它实际上隐式的返回的时total.bookNo
但这只是比较表层的解释。
实际上,C++中有一个隐含的this指针。当我们通过一个对象调用isbn()时,C++会将这个对象的地址赋给this指针。
举一个例子吧! 当调用total.isbn()时,C++会将total的地址赋给this指针。而this指针时isbn()的一个隐式形参,在isbn()内部,直接使用调用该函数的对象的成员 等价于 通过this指针来调用。也就是 return bookNo 等价于 return this->bookNo。所以我们正确返回了total的bookNo成员。
3. const成员函数: 就一句话:常量成员函数不能改变调用它的对象的内容。例如上面,isbn()可以读取total的内容,但不能改变它们。
4. combine()函数: 之所以combine()函数返回一个Sales_Data的引用,是因为这里想模仿 +=运算符。其实返回void 程序也是没问题的。
看一下它是怎么运行的: total.combine(trans) this指针绑定的时total,rhs绑定的时trans,我们将trans的内容加到total并返回。
5. 非成员接口函数: 非成员接口函数的声明在类的头文件中类外的地方,定义在类的cpp文件中。