sales_data.h文件
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
using namespace std;
struct Sales_data{
//新成员:关于Sales_data对象的操作
std::string isbn() const {return bookNo;}
Sales_data& combine(const Sales_data&);
double avg_price() const;
//数据成员
std::string bookNo;
unsigned units_sold =0;
double revenue =0.0;
};
//Sales_data的非成员函数接口
Sales_data add(const Sales_data&,const Sales_data&);
std::ostream &print(std::ostream&,const Sales_data&);
std::istream &read(std::istream&,Sales_data&);
#endif // SALES_DATA_H
Sales_data.c文件
#include "sales_data.h"
//函数定义
double Sales_data::avg_price() const {
if(units_sold)
return revenue/units;
else
return 0;
}
Sales_data& Sales_data::combine(const Sales_data& rhs){
units_sold+=rhs.units_sold;
revenue+=rhs.revenue;
return *this;
}
问题1:std::string isbn() const {return bookNo;}函数中只有一条return语句,用于返回 Sales_data对象的bookNo数据成员,它是如何获得bookNo成员所依赖的对象的呢?
解释:看一下成员函数isbn()的调用:
total.isbn();
成员函数通过一个名为this的额外的隐式参数来访问调用它的哪个对象。当我们调用一个成员函数时,用请求该函数对象地址来初始化this。例如,如果调用total.isbn();则编译器负责把total的地址传递给isbn的隐式形参this,可以等价的认为编译器将该调用重写出了 以下形式:
//伪代码,用于说明调用成员函数的实际执行过程
Sales_data::isbn(&total)
其中,在调用Sales_data的成员isbn时传入了total的地址。在成员函数内部,我们可以直接使用调用该函数的对象的成员,而无需通过成员访问运算符来做到这一点,因为this所指的正是这个对象,任何对类成员的直接访问都被看做this的隐式引用,也就是说,当isbn使用bookNo时,它隐式地使用this指向的成员,就像我们书写了this->bookNo一样。
问题2: std::string isbn() const {return bookNo;}函数中的const有何作用?
解释:const的作用是修改隐式this指针的类型。
默认情况下,this指针是指向类类型非常量版本的常量指针。例如在Sales_data的成员函数中,this的类型是Sales_data *const。尽管this是隐式的,但它还是要遵循初始化原则,意味着在默认情况下我们不能把this绑定到一个常量对象上。这就使得我们不能在一个常量对象上调用普通的成员函数。如果isbn是一个普通的成员函数而且this是一个普通的指针参数,则我们应该把this声明成const Sales_data *const。毕竟,在isbn函数体内不会改变this所指的对象,所以把this设置为指向常量的指针有助于提高函数的灵活性。然而,this是隐式的不会出现在参数列表中,所以在哪儿将this声明为指向常量的指针将成为我们必须面对的问题。C++语言的做法是允许把const关键字放在成员函数的列表之后,此时紧跟在参数列表后面的const表示this是一个指向常量的指针。像这样使用const的成员函数称为常量成员函数。