《C++ Primer》5th 课后练习 第七章 类 41~50

练习7.41 使用委托构造函数重新编写你的Sales_data 类,给每个构造函数体添加一条语句,令其一旦执行就打印一条信息。用各种可能的方式分别创建 Sales_data 对象,认真研究每次输出的信息直到你确实理解了委托构造函数的执行顺序。

//Sale_data.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
struct Sales_data {
	friend istream &read(istream &is, Sales_data &item);
	friend ostream &print(ostream &os, const Sales_data &item);
	friend Sales_data add(const Sales_data &a, const Sales_data &b);

public:
	Sales_data(const string &s, const unsigned cnt, const double p) :
		bookNo(s), units_sold(cnt), revenue(cnt*p) {
		cout << "I have three para" << endl;
	}

	Sales_data():Sales_data("", 0, 0) {
		cout << "I have zero para" << endl;
	};
	Sales_data(const string &s) : Sales_data(s, 0, 0) {
		cout << "I have one para" << endl;
	}
	Sales_data(istream &is):Sales_data() {
		cout << "I have one istream para" << endl;
		double price;
		is >> this->bookNo >> this->units_sold >> price;
		this->revenue = this->units_sold * price;
	}
	string isbn()const { return this->bookNo; }
	Sales_data &combine(const Sales_data &other);

private:
	inline double avg_price() const;
	string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};
inline
double Sales_data::avg_price() const
{
	return units_sold ? revenue / units_sold : 0;
}
istream &read(istream &is, Sales_data &item);
ostream &print(ostream &os, const Sales_data &item);
Sales_data add(const Sales_data &a, const Sales_data &b);
//Sale_data.cpp
#include"Sale_data.h"

//Sales_data::Sales_data(istream &is) {
//	read(is, *this);
//}
Sales_data &Sales_data::combine(const Sales_data &other) {
	this->units_sold += other.units_sold;
	this->revenue += other.revenue;
	return *this;
}
istream &read(istream &is, Sales_data &item) {
	double price;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = item.units_sold * price;
	return is;
}
ostream &print(ostream &os, const Sales_data &item) {
	os << item.bookNo << " " << item.units_sold << " " << item.revenue;
	return os;
}
Sales_data add(const Sales_data &a, const Sales_data &b) {
	Sales_data sum = a;
	sum.combine(b);
	return sum;
}
#include "Sale_data.h"
int main(int argc, char **argv)
{
	Sales_data a("111", 0, 0);
	cout << endl;
	Sales_data b;
	cout << endl;
	Sales_data c("222");
	cout << endl;
	Sales_data d(cin);
	return 0;
}

运行结果:

I have three para

I have three para
I have zero para

I have three para
I have one para

I have three para
I have zero para
I have one istream para
123 1 2

如果有委托构造函数,则先执行委托构造函数,将所有递归的委托构造函数执行完之后再执行自己。

练习7.42 对于你在练习7.40中编写的类,确定哪些构造函数可以使用委托。如果可以的话,编写委托构造函数。如果不可以,从抽象概念列表中重新选择一个你认为可以使用委托构造函数的,为挑选出的这个概念编写类定义。

#pragma once
//Employee.h
#include<string>
class Employee
{
public:
	Employee() = default;//默认构造一个空的对象
	Employee(const std::string &s, int sly, int dpt, int wy = 0) : emNum(s), salary(sly), department(dpt), workYear(wy) {};//传入全部参数进行构造
	Employee(const Employee &oth):Employee() //委托构造
					{ *this = oth; }//拷贝构造

	~Employee();
private:
	std::string emNum = "";
	int salary = 0;
	int department = 0;
	int workYear = 0;
};
Employee::~Employee()
{

}

练习7.43 假定有一个名为 NoDefault 的类,它有一个接受 int 的构造函数,但是没有默认构造函数。定义类 C,C 有一个 NoDefault 类型的成员,定义C 的默认构造函数。

class NoDefault{
public:
	NoDefault(int c){}
}
class C{
public:
    C():def(0){}
private:
    Nodefault d;
}

练习7.44 下面这条声明合法吗?如果不,为什么?

vector<NoDefault> vec(10);

不合法,NoDefault类没有默认

练习7.45 如果在上一个练习中定义的vector的元素类型是C,则声明合法吗?为什么?

合法,C有默认构造函数。

练习7.46 下面哪些论断是不正确的?为什么?

(a) 一个类必须至少提供一个构造函数。
(b) 默认构造函数是参数列表为空的构造函数。
© 如果对于类来说不存在有意义的默认值,则类不应该提供默认构造函数。
(d) 如果类没有定义默认构造函数,则编译器将为其生成一个并把每个数据成员初始化成相应类型的默认值。

(a)错误,因为如果没有显式地声明构造函数,那么编译器会帮助我们隐式地定义一个默认构造函数,称为合成的默认构造函数。

(b)错误,也可以是,为每个参数都提供了默认值的构造函数。

(c)错误,用该类型创建容器或直接声明非静态变量时,若没有默认构造函数,将产生错误。

(d)错误,当类没有构造函数时,编译器才会创建默认构造函数。

练习7.47 说明接受一个string 参数的Sales_data构造函数是否应该是explicit的,并解释这样做的优缺点。

我觉得应该是explicit的。

优点:

  • 避免了造成使用者发生一些低级错误。

缺点:

  • 导致构造函数在使用时不那么灵活。

练习7.48 假定Sales_data 的构造函数不是explicit的,则下述定义将执行什么样的操作?

string null_isbn("9-999-9999-9");
Sales_data item1(null_isbn);
Sales_data item2("9-999-99999-9");

这些定义跟exlicit无关吧?

练习7.49 对于combine 函数的三种不同声明,当我们调用i.combine(s) 时分别发生什么情况?其中 i 是一个 Sales_data,而 s 是一个string对象。

(a) Sales_data &combine(Sales_data); // ok
(b) Sales_data &combine(Sales_data&); // error C2664: 无法将参数 1 从“std::string”转换为“Sales_data &”	
(c) Sales_data &combine(const Sales_data&) const; // 该成员函数是const 的,意味着不能改变对象。而 combine函数的本意就是要改变对象

练习7.50 确定在你的Person 类中是否有一些构造函数应该是 explicit 的。

explicit Person(istream &is) { read(is, *this); }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值