习题答案至于一个.cc 中,需要演示某一题直接修改 #define NUM***, 如运行7.23题为#define NUM723;
chapter 7
1、
定义在类内部的函数时隐式的inline函数
成员函数通过一个名为this的额外的参数来访问调用它的那个对象,当我们调用一个成员函数时,用请求该函数的对象地址初始化this,比如调用total.isbn()时,
编译器负责把total的地址传递给isbn的隐式形参this,可以等价认为编译重写为:
Sales_data::ibsn(&total),
其中,调用Sales_data的isbn成员时传入;额total的地址。
this总是执行啊这个对象,所以this是一个常量指针。
this设置为指向常量的指针有助于提高函数的灵活性。
紧跟在参数列表之后的const表示this是一个指向常量的指针。这一函数称为常量成员函数。
2、
一般来说,执行输出任务的函数应该尽量减少对格式的控制,这样可以确保由用户代码来决定是够换行。
不同的构造函数之间必须在参数数量或参数类型上有所区别。
构造函数不能被声明成const的。
默认的构造函数无需任何实参,编译器创建的构造函数称为合成的默认构造函数:
如果存在类内的初始值,用其来初始化成员。否则,默认初始化该成员。
如果在类外定义构造函数,因为其没有返回值,必须指明是哪个类的成员。
使用this将对象作为一个整体访问,而非直接访问对象的某个成员。
使用*this将this对象作为实参传递给成员函数。
3、
当希望定义的类所有成员时public时,使用struct;反之,如希望成员时private,使用class。
友元声明出现在类定义的内部,一般最好在类定义开始或结束前的位置集中声明友元。
友元不是类成员,也不受它所在区域访问级别的约束。
友元的声明仅仅指定了访问的权限,而非通常意义上的函数声明。所以要在友元函数之外另起声明。
4、
当我们提供一个类内初始值时,必须以符号=或花括号表示。
一个const成员函数如果以引用的形式返回*this,那么它的返回类型将是常量引用。
类名用来直接指向类类型,也可以将类名跟于class/struct之后:
Sales_data item1;
class Sales_data item1; //等价的声明
5、
友元关系不存在传递性,每个类负责控制自己的友元函数。
名字查找(name lookup)
现在在名字所在的块中寻找其声明语句,只考虑在名字的使用之前出现的声明。
如果没找到,继续查找外层作用域。
最终没找打,报错。
类的定义分为两步: 首先,编译成员的声明;直到类全部可见后才编译函数体。
6、
类型名的定义通常出现在类的开始处,这样能确保所有使用该类型的成员都出现在类名的定义之后。一般不建议使用其他成员的名字作为某个成员函数的参数。
成员是const、引用,或者属于某种未提供默认构造函数的类类型,必须通过构造函数初始值为这些成员提供初值。
构造函数初始值的顺序与成员声明的顺序保持一致。
7、
如果一个构造函数为所有参数都提供了默认实参,则它实际上也定义了默认的构造函数。
实际中,如果定义了其他构造函数,那么最好也提供一个默认的构造函数。
8、
静态成员函数不能与任何对象绑定在一起,它们不包含this指针。静态成员函数也不能声明成const的,并且也不能在static函数体内使用this指针。
非静态数据成员不能作为默认实参,因为它的值本身属于对象的一部分,如果这门做就无法真正提供一个对象以便从中获取成员的值,引发错误。
#ifndef CHAPTER7_H
#define CHAPTER7_H
//Chapter7.h
#include
#include
using namespace std;
class Sales_data;
istream &read(istream &is, Sales_data &item);
class Sales_data {
friend Sales_data add(const Sales_data &lhs, const Sales_data &rhs);
friend istream &read(istream &is, Sales_data &item);
friend ostream &print(ostream &os, const Sales_data &item);
public:
Sales_data(){};
Sales_data(const string &s):bookNo(s), units_sold(0), revenue(0.0){ }
Sales_data(const string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p){ };
Sales_data(istream &is){
read(is, *this);
}
string isbn() const{ return bookNo; }
Sales_data& combine(const Sales_data&);
private:
inline double avg_prive() const;
string bookNo;
unsigned units_sold;
double revenue;
};
Sales_data& Sales_data::combine(const Sales_data& rhs){
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
double Sales_data::avg_prive() const{
return units_sold ? revenue / units_sold : 0;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs){
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
istream &read(istream &is, Sales_data &item){
double price(0.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 << " " <> p.name >> p.address;
if(!is)
p = Person();
return is;
}
ostream &print(ostream &os, const Person &p){
os << p.getName() << p.getAddress();
return os;
}
class Screen;
class Window_mgr{
public:
typedef vector::size_type ScreenIndex;
inline void clear(ScreenIndex);
private:
vector screens;
};
class Screen{
friend void Window_mgr::clear(ScreenIndex);
public:
typedef string::size_type pos;
Screen(){}
Screen(pos ht, pos wd): height(ht), width(wd), contents(ht * wd, ' ') { }
Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c){}
char get(){ return contents[cursor]; }
char get(pos r, pos c) const { return contents[r * width + c]; }
inline Screen &set(char c);
inline Screen &set(pos r, pos c, char ch);
inline Screen &move(pos r, pos c);
const Screen &display(ostream &os) const{
os << contents;
return *this;
}
pos size() const;
private:
pos cursor;
pos height, width;
string contents;
};
Screen::pos Screen::size() const{
return height * width;
}
inline Screen &Screen::set(char c){
contents[cursor] = c;
return *this;
}
inline Screen &Screen::set(pos r, pos col, char ch){
contents[r * width + col] = ch;
return *this;
}
inline Screen &Screen::move(pos r, pos c){
pos row = r * width + c;
cursor = row + c;
return *this;
}
#endif
//main.cc
#include
#include
#include
#include "Chapter7.h"
using namespace std;
#define NUM758
/*7.1*/
#ifdef NUM71
struct Sales_data{
string bookNo;
unsigned units_sold;
double revenue;
};
#endif
/*7.2*/
#ifdef NUM72
struct Sales_data {
string isbn() const{ return bookNo; }
Sales_data& combine(const Sales_data&);
string bookNo;
unsigned units_sold;
double revenue;
};
Sales_data& Sales_data::combine(const Sales_data& rhs){
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
#endif
/*7.4*/
#ifdef NUM74
class Person{
string name;
string address;
};
#endif
/*7.5*/
#ifdef NUM75
class Person{
string name;
string address;
string getName() const { return name; }
string getAddress()const { return address; }
};
#endif
/*7.31*/
#ifdef NUM731
class Y;
class X{
Y *p = nullptr;
};
class Y{
X b;
};
#endif
/*7.35*/
#ifdef NUM735
typedef string Type;
Type initVal(); //use 'string'
class Exercise{
public:
typedef double Type;
Type setVal(Type); //use 'double'
Type initVal(){ //use 'double'
return val;
}
private:
int val;
};
Exercise::Type Exercise::setVal(Type parm){ //first uses 'string', second uses 'double'
val = parm + initVal(); //use 'double'
return val;
}
#endif
/*7.58*/
#ifdef NUM758
class Example{
public:
static double rate;
static const int vecSize = 20;
static vector vec;
};
#endif
int main(){
/*7.1*/
#ifdef NUM71
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(total.bookNo == trans.bookNo){
total.units_sold += trans.units_sold;
total.revenue += trans.revenue;
}else{
cout << total.bookNo <<" "<> total.bookNo >> total.units_sold >> total.revenue){
Sales_data trans;
while(cin >> trans.bookNo >> trans.units_sold >> trans.revenue){
if(total.isbn() == trans.isbn())
total.combine(trans);
else{
cout << total.bookNo <<" "<"<> no_ >> name_ >> author_ >> pubdate_; }
private:
unsigned no_;
string name_;
string author_;
string pubdate_;
};
#endif
/*7.41*/
#ifdef NUM741
cout << "1.Default way: "<> no_ >> name_ >> author_ >> pubdate_; }
private:
unsigned no_;
std::string name_;
std::string author_;
std::string pubdate_;
};
#endif
/*7.43*/
#ifdef NUM743
class NoDefault{
public:
NoDefault(int){}
};
class C{
public:
C(): member(0){} //定义C的构造函数
private:
NoDefault member;
};
#endif
/*7.44*/
#ifdef NUM744
cout <<"不合法,应为vector有10个元素,每个都必须被默认初始化。但临时变量显然没有默认初始化. "< vec; vector;"<
参考资料: