《C++ primer》第五版习题答案整理——第七章 类

7.1

#include <iostream>
#include <vector>
using namespace std;

struct Sales_data
{
	std::string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
};

int main()
{
	Sales_data info;
	Sales_data temp;
	while (cin >> info.bookNo >> info.units_sold >> info.revenue)
	{
		if (temp.bookNo.empty())
		{
			temp = info;
		}
		else if (info.bookNo == temp.bookNo)
		{
			temp.units_sold += info.units_sold;
			temp.revenue += info.revenue;
		}
		else {
			cout << "bookNo:" << temp.bookNo << " units_sold:" << temp.units_sold << " revenue:" << temp.revenue << endl;
			temp = info;
		}
	}
	cout << "bookNo:" << temp.bookNo << " units_sold:" << temp.units_sold << " revenue:" << temp.revenue << endl;
	return 0;
}

7.2

#include <iostream>
#include <vector>
using namespace std;

struct Sales_data
{
	string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
	double price = 0.0;//单价
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
};

Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	price = revenue / units_sold;
	return *this;
}

7.3

#include <iostream>
#include <vector>
using namespace std;

struct Sales_data
{
	string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
	double price = 0.0;//单价
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
};

Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	price = revenue / units_sold;
	return *this;
}

int main()
{
	Sales_data info;
	Sales_data temp;
	while (cin >> info.bookNo >> info.units_sold >> info.revenue)
	{
		info.price = info.revenue / info.units_sold;
		if (temp.bookNo.empty())
		{
			temp = info;
		}
		else if (info.isbn() == temp.isbn())
		{
			temp.combine(info);
		}
		else {
			cout << "bookNo:" << temp.bookNo << " units_sold:" << temp.units_sold << " revenue:" << temp.revenue << " price:" << temp.price << endl;
			temp = info;
		}
	}
	cout << "bookNo:" << temp.bookNo << " units_sold:" << temp.units_sold << " revenue:" << temp.revenue << " price:" << temp.price << endl;
	return 0;
}

7.4

struct Person
{
	string Name;//姓名
	string adress;//住址
};

7.5

应是const,因其只需读取,无需改变;

struct Person
{
	string Name;//姓名
	string Adress;//住址
	string get_Name() const { return Name; }
	string get_Adress() const { return Adress; }
};

7.6 & 7.7

#include <iostream>
#include <vector>
using namespace std;

struct Sales_data
{
	string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	double avg_price()const;
};

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
{
	if (units_sold)
	{
		return revenue / units_sold;
	}
	else {
		return 0;
	}
}

istream& read(std::istream& is, Sales_data& item)
{
	double price = 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 << " " << item.revenue << " " << item.avg_price();
	return os;
}

Sales_data add(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum.combine(rhs);
	return sum;
}

int main()
{
	Sales_data info;
	Sales_data temp;
	while (read(cin,info))
	{
		if (temp.bookNo.empty())
		{
			temp = info;
		}
		else if (info.isbn() == temp.isbn())
		{
			temp=add(info, temp);
		}
		else {
			print(cout,temp);
			temp = info;
		}
	}
	print(cout, temp);
	return 0;
}

7.8

read函数需改变成员对象;
print函数无需改变成员对象;

7.9

#include <iostream>
#include <vector>
using namespace std;

struct Person
{
	string Name;//姓名
	string Adress;//住址
	string get_Name() const { return Name; }
	string get_Adress() const { return Adress; }
};

istream &Read(istream &is, Person &item)
{
	is >> item.Name >> item.Adress;
	return is;
}

ostream& Print(ostream& os, const Person& item)
{
	os << item.get_Name() <<" " << item.get_Adress();
	return os;
}

7.10

读入data1和data2并判断是否为真;

7.11

#include <iostream>
using namespace std;

struct Sales_data
{
	//构造函数
	Sales_data() = default;
	Sales_data(string& s) :bookNo(s) {}
	Sales_data(string& s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p* n) {}
	Sales_data(istream&);
	//其他成员
	string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	double avg_price()const;
};

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
{
	if (units_sold)
	{
		return revenue / units_sold;
	}
	else {
		return 0;
	}
}

istream& read(std::istream& is, Sales_data& item)
{
	double price = 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 << " " << item.revenue << " " << item.avg_price();
	return os;
}

Sales_data add(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum.combine(rhs);
	return sum;
}

Sales_data::Sales_data(istream& is)
{
	read(is, *this);
}

int main()
{
	Sales_data exp0;
	print(cout, exp0) << endl;
	string str = "0001";
	Sales_data exp1(str);
	print(cout, exp1) << endl;
	str = "0002";
	Sales_data exp2(str, 5, 10.5);
	print(cout, exp2) << endl;
	Sales_data exp3(cin);
	print(cout, exp3) << endl;
}

7.12

#include <iostream>
using namespace std;

struct Sales_data;
istream& read(std::istream& is, Sales_data& item);

struct Sales_data
{
	//构造函数
	Sales_data() = default;
	Sales_data(string & s) :bookNo(s) {}
	Sales_data(string & s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p * n) {}
	Sales_data(istream & is) { read(is, *this); }
	//其他成员
	string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	double avg_price()const;
};

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
{
	if (units_sold)
	{
		return revenue / units_sold;
	}
	else {
		return 0;
	}
}

istream& read(std::istream& is, Sales_data& item)
{
	double price = 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 << " " << item.revenue << " " << item.avg_price();
	return os;
}

Sales_data add(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum.combine(rhs);
	return sum;
}

//Sales_data::Sales_data(istream& is)
//{
//	read(is, *this);
//}

int main()
{
	Sales_data exp0;
	print(cout, exp0) << endl;
	string str = "0001";
	Sales_data exp1(str);
	print(cout, exp1) << endl;
	str = "0002";
	Sales_data exp2(str, 5, 10.5);
	print(cout, exp2) << endl;
	Sales_data exp3(cin);
	print(cout, exp3) << endl;
}

7.13

int main()
{
	Sales_data total(cin);
	if (!total.isbn().empty())
	{
		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 {
		cerr << "No Data?!" << endl;
	}
	return 0;
}

7.14

	Sales_data() : bookNo(string()), units_sold(0), revenue(0.0) { }

7.15

#include <iostream>
using namespace std;

struct Person;
istream& Read(istream& is, Person& item);
ostream& Print(ostream& os, const Person& item);

struct Person
{
	Person() = default;
	Person(string& s) :Name(s) {}
	Person(string& s0, string& s1) :Name(s0), Adress(s1) {}
	Person(istream& is) { Read(is, *this); }
	string Name;//姓名
	string Adress;//住址
	string get_Name() const { return Name; }
	string get_Adress() const { return Adress; }
};

istream& Read(istream& is, Person& item)
{
	is >> item.Name >> item.Adress;
	return is;
}

ostream& Print(ostream& os, const Person& item)
{
	os << item.get_Name() << " " << item.get_Adress();
	return os;
}

7.16

一个类可以包含0个或多个访问说明符,而且对于某个访问说明符能出现多少次也没有严格规定;
如果某个成员需要在整个程序内都被访问,那么它应该定义为 public; 如果某个成员只能在类内部访问,那么它应该定义为 private。

7.17

使用class和struct定义类唯一的区别就是默认的访问权限:
使用class默认访问权限:private;
使用struct默认访问权限:public。

7.18

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问成员变量private,提供对应的getXxx()/setXxx()方法。
通过方法来控制成员变量的操作,提高了代码的安全性;把代码用方法进行封装,提高了代码的复用性

7.19

class Person
{
	friend istream& Read(istream& is, Person& item);
public:
	Person() = default;
	Person(string & s) :Name(s) {}
	Person(string & s0, string & s1) :Name(s0), Adress(s1) {}
	Person(istream & is) { Read(is, *this); }
	string get_Name() const { return Name; }
	string get_Adress() const { return Adress; }
private:
	string Name;//姓名
	string Adress;//住址
};

构造函数、getName()、getAddress() 函数将设为 public。name 和 address 将设为private。
函数是暴露给外部的接口,因此要设为public;而数据则应该隐藏让外部不可见。

7.20

访问非公有成员时有用;
利:与当前类有关的接口函数能直接访问类的私有变量。
弊:破坏了封装性。

7.21

#include <iostream>
using namespace std;

class Sales_data;
istream& read(std::istream& is, Sales_data& item);
ostream& print(ostream&, const Sales_data&);
Sales_data add(const Sales_data&, const Sales_data&);

class Sales_data
{
	friend istream& read(istream&, Sales_data&);
	friend ostream& print(ostream&, const Sales_data&);
	friend Sales_data add(const Sales_data&, const Sales_data&);
public:
	Sales_data() = default;
	Sales_data(string& s) :bookNo(s) {}
	Sales_data(string& s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p* n) {}
	Sales_data(istream& is) { read(is, *this); }
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
private:
	string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
	double avg_price()const;
};

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
{
	if (units_sold)
	{
		return revenue / units_sold;
	}
	else {
		return 0;
	}
}

istream& read(std::istream& is, Sales_data& item)
{
	double price = 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 << " " << item.revenue << " " << item.avg_price();
	return os;
}

Sales_data add(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum.combine(rhs);
	return sum;
}

7.22

#include <iostream>
using namespace std;

class Person;
istream& Read(istream& is, Person& item);
ostream& Print(ostream& os, const Person& item);

class Person
{
	friend istream& Read(istream&, Person&);
	friend ostream& Print(ostream&, const Person&);
public:
	Person() = default;
	Person(string & s) :Name(s) {}
	Person(string & s0, string & s1) :Name(s0), Adress(s1) {}
	Person(istream & is) { Read(is, *this); }
	string get_Name() const { return Name; }
	string get_Adress() const { return Adress; }
private:
	string Name;//姓名
	string Adress;//住址
};

istream& Read(istream& is, Person& item)
{
	is >> item.Name >> item.Adress;
	return is;
}

ostream& Print(ostream& os, const Person& item)
{
	os << item.get_Name() << " " << item.get_Adress();
	return os;
}

7.23&&7.24

#include <iostream>
using namespace std;

class Screen
{
public:
	using pos = string::size_type;
	Screen() = default;
	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()const { return contents[cursor]; }
	inline char get(pos r, pos c) const;
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	string contents;
};

char Screen::get(pos r, pos c)const
{
	pos row = r * width;
	return contents[row + c];
}

7.25

能,
Screen 的成员只有内置类型和 string,因此能安全地依赖于拷贝和赋值操作的默认版本。管理动态内存的类则不能依赖于拷贝和赋值操作的默认版本,而且也应该尽量使用string 和 vector 来避免动态管理内存的复杂性。

7.26

class Sales_data
{
	friend istream& read(istream&, Sales_data&);
	friend ostream& print(ostream&, const Sales_data&);
	friend Sales_data add(const Sales_data&, const Sales_data&);
public:
	Sales_data() = default;
	Sales_data(string& s) :bookNo(s) {}
	Sales_data(string& s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p* n) {}
	Sales_data(istream& is) { read(is, *this); }
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
private:
	string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
	inline double avg_price()const;
};

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
{
	if (units_sold)
	{
		return revenue / units_sold;
	}
	else {
		return 0;
	}
}

istream& read(std::istream& is, Sales_data& item)
{
	double price = 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 << " " << item.revenue << " " << item.avg_price();
	return os;
}

Sales_data add(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum.combine(rhs);
	return sum;
}

7.27

#include <iostream>
using namespace std;

class Screen
{
public:
	using pos = string::size_type;
	Screen() = default;
	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()const { return contents[cursor]; }
	inline char get(pos r, pos c) const;
	Screen& move(pos r, pos c);
	Screen& set(char);
	Screen& set(pos, pos, char);
	Screen& display(ostream& os) { os << contents; return*this; }
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	string contents;
};

char Screen::get(pos r, pos c)const
{
	pos row = r * width;
	return contents[row + c];
}

Screen& Screen::move(pos r, pos c)
{
	pos row = r * width;
	cursor = row + c;
	return *this;
}

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;
}

int main()
{
	Screen myScreen(5, 5, 'X');
	myScreen.move(4, 0).set('#').display(cout);
	cout << "\n";
	myScreen.display(cout);
	cout << "\n";
}

7.28

返回类型是Screen的输出:
XXXXXXXXXXXXXXXXXXXX#XXXX
XXXXXXXXXXXXXXXXXXXXXXXXX
当返回类型不使用引用时,move、set和display返回的是Screen的临时副本,操作并不会改变myScreen。

7.29

正确

7.30

优点:
1:程序的意图更明确。当需要将一个对象作为整体引用而不是引用对象的一个成员时,使用this,则该函数返回对调用该函数的对象的引用。
2:可以非常明确地指出访问的是调用该函数的对象的成员,且可以在成员函数中使用与数据成员同名的形参。
缺点:有时候显得有点多余。

7.31

class Y;

class X {
	Y* y = nullptr;
};

class Y {
	X x;
};

7.32

#include <iostream>
#include <vector>
using namespace std;

class Screen;
class Window_mgr;
class Screen
{
	friend class Window_mgr;
public:
	using pos = string::size_type;
	Screen() = default;
	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()const { return contents[cursor]; }
	inline char get(pos r, pos c) const;
	Screen& move(pos r, pos c);
	Screen& set(char);
	Screen& set(pos, pos, char);
	Screen& display(ostream& os) { os << contents; return*this; }
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	string contents;
};

class Window_mgr {
public:
	using ScreenIndex = std::vector<Screen>::size_type;
	void clear(ScreenIndex);
private:
	vector<Screen> screens{ Screen(24,80,' ') };
};

char Screen::get(pos r, pos c)const
{
	pos row = r * width;
	return contents[row + c];
}

Screen& Screen::move(pos r, pos c)
{
	pos row = r * width;
	cursor = row + c;
	return *this;
}

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;
}

void Window_mgr::clear(ScreenIndex i)
{
	Screen s = screens[i];
	s.contents = string(s.height * s.width, ' ');
}

7.33

未定义标识符 pos

Screen::pos Screen::size()const
{
	return height * width;
}

7.34

在该类作用域内使用pos的地方显示:未定义标识符“pos”。

7.35

typedef string Type;
Type initVal(); // use `string`
class Exercise {
public:
    typedef double Type;
    Type setVal(Type); // use `double`
    Type initVal(); // use `double`
private:
    int val;
};

Type Exercise::setVal(Type parm) {  // first is `string`, second is `double`
    val = parm + initVal();     // Exercise::initVal()
    return val;
}

修改:

Exercise::Type Exercise::setVal(Type parm) {  // first is `double`, second is `double`
    val = parm + initVal();     // Exercise::initVal()
    return val;
}

7.36

成员初始化顺序和类中定义的顺序一致,故先初始化rem,后初始化base,初始化rem需要用到base,故程序报错;

struct X {
	X (int i, int j): base(i), rem(base % j) {}
	int base, rem;
};

7.37

Sales_data first_item(cin); // 使用 Sales_data(std::istream &is) ; 各成员值从输入流中读取
int main() {
	Sales_data next; // 使用默认构造函数  bookNo = "", cnt = 0, revenue = 0.0
	Sales_data last("9-999-99999-9"); // 使用 Sales_data(std::string s = "");   bookNo = "9-999-99999-9", cnt = 0, revenue = 0.0
}

7.38

Sales_data(std::istream &is = std::cin) { read(is, *this); }

7.39

非法,重载Sale_data()将不明确;

7.40

#include <iostream>
using namespace std;

class Employee
{
public:
	Employee() = default;
	Employee(istream& is) { is >> name >> age >> adress; }
	Employee(string n, int ag, string ad) :name(n), age(ag), adress(ad) {}
private:
	string name;
	int age;
	string adress;
};

7.41

class Sales_data
{
	friend istream& read(istream&, Sales_data&);
	friend ostream& print(ostream&, const Sales_data&);
	friend Sales_data add(const Sales_data&, const Sales_data&);
public:
	Sales_data(string s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p* n) { cout << "Sales_data(string s, unsigned n, double p)" << endl; }
	Sales_data() :Sales_data("", 0, 0) { cout << "Sales_data()" << endl; }
	Sales_data(string s) :Sales_data(s, 0, 0) { cout << "Sales_data(string s)" << endl; }
	Sales_data(istream& is):Sales_data() { read(is, *this);cout << "Sales_data(istream& is)" << endl; }
	string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
private:
	string bookNo;
	unsigned units_sold = 0;//销量
	double revenue = 0.0;//收入
	inline double avg_price()const;
};

7.42

#include <iostream>
using namespace std;

class Employee
{
public:
	Employee(string n, int ag, string ad) :name(n), age(ag), adress(ad) {}
	Employee() :Employee("",0,"") {}
	Employee(istream& is) { is >> name >> age >> adress; }
private:
	string name;
	int age;
	string adress;
};

7.43

class NoDefault
{
public:
	NoDefault(int num) {}
};

class c
{
public:
	c() :nodefault(0) {}
private:
	NoDefault nodefault;
};

7.44

非法,NoDefault 没有默认构造函数。

7.45

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

7.46

(a)正确,如果我们的类没有显式地定义构造函数,那么编译器就会为我们隐式地定义一个默认构造函数,并称之为合成的默认构造函数。
(b)不正确,为每个参数都提供了默认值的构造函数也是默认构造函数。
©不正确,哪怕没有意义的值也需要初始化。
(d)不正确,只有当一个类没有显式定义任何构造函数的时候,编译器才会生成一个默认构造函数;引用和指针数据成员没有合成默认构造函数。

7.47

都可以,取决于我们对用户使用该转换的看法。
P264原文:是否需要从string到sales_data的转换依赖于我们对用户使用该转换的看法。在此例中,这种转化可能是对的。null_book中的string可能表示了一个不存在的ISBN编号。
优点:

  • 可以抑制构造函数定义的隐式转换;
  • 可以定义一个只能使用直接初始化形式的构造函数;

缺点:

  • 只对一个实参的构造函数有效;

7.48

无影响,调用构造函数,未发生隐式类型转换。

7.49

  • (a) string隐式类型转换为Sales_data,传入临时量副本;
  • (b) 错误:无法将string隐式转换为Sales_data&,combine的参数时非常量的引用,我们不能将临时参数传递给它,改为:Sales_data &combine(const Sales_data&);
  • © 错误,string隐式转换为Sales_data,传给常量引用,但常量成员函数不能改变 this。

7.50

	explicit Person(string & s) :Name(s) {}
	explicit Person(istream & is) { Read(is, *this); }

7.51

比如:

int getSize(const std::vector<int>&);

如果不是explicit,可以这样使用

getSize(34);

是混乱的。
string则不同,string的单参数构造函数的参数是const char * ,因此凡是在需要用到string的地方都可以用const char *来代替(字面值就是const char *)。如:

    void print(std::string);
    print("hello world");

7.52

错误,Sales_data类不是聚合类,不能使用显式地初始化类的对象。
需要把Sales_data类,改为聚合类:

struct Sales_data {
    std::string bookNo;
    unsigned units_sold;
    double revenue;
};

7.53

class Debug {
public:
	constexpr Debug(bool b = true) : hw(b), io(b), other(b) { }
	constexpr Debug(bool h, bool i, bool o) : hw(h), io(i), other(0) { }

	constexpr bool any() { return hw || io || other; }
	void set_hw(bool b) { hw = b; }
	void set_io(bool b) { io = b; }
	void set_other(bool b) { other = b; }
private:
	bool hw;
	bool io;
	bool other;
};

7.54

不能,constexpr函数有限制:1)函数返回类型及所有形参地类型必须是字面值类型;2)必须有且只有一条返回语句;
在c++11中,constexpr函数不能改变数据成员,c++14中没有这个特点;

7.55

不是
std::string 不是字面值类型。

#include <string>
#include <iostream>
#include <type_traits>

struct Data {
    int ival;
    std::string s;
};

int main()
{
    std::cout << std::boolalpha;
    std::cout << std::is_literal_type<Data>::value << std::endl;
    // output: false
}

7.56

类的静态成员与类本身直接相关,而不是与类的各个对象相互关联;
但是我们仍然可以使用类作用域运算符访问静态成员,加上static关键字即可声明;
每个对象不需要存储公共数据,如果数据被改变,则每个对象都可以使用新值;
静态成员与普通成员区别:

  • 静态数据成员可以是不完全型;
  • 可以使用静态成员作为默认实参;

7.57

class Account {
public:
	void calculate() { amount += amount * interestRate; }
	static double rate() { return interestRate; }
	static void rate(double);
private:
	std::string owner;
	double amount;
	static double interestRate;
	static double initRate() { return 0; };
};

void Account::rate(double newRate)
{
	interestRate = newRate;
}

double Account::interestRate = initRate();

7.58

通常情况下,类的静态成员不应该在类的内部初始化。然而,

  1. 我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr
  2. 初始值必须是常量表达式,因为这些成员本身就是常量表达式,所以它们能用在所有适合于常量表达式的地方。
// example.h
class Example {
public:
    static constexpr double rate = 6.5;//rate改为常量表达式
    static const int vecSize = 20;
    static vector<double> vec;//vector是模板不是字面值常量类型,故只能声明,不能被初始化。
};
 
// example.C
#include "example.h"
constexpr double Example::rate;
vector<double> Example::vec(Example::vecSize);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值