C++Prime 第七章前30题
练习7.1
书上代码照着敲就行.
练习7.2
#include <iostream>
#include "Sales_data.h"
using namespace std;
int main()
{
Sales_data total;
if (cin >> total)
{
Sales_data trans;
while (cin >> trans)
{
if (total.isbn() == trans.isbn())
total.combine(trans);
else
{
cout << total << endl;
}
}
}
else {
cout << "No data??" << endl;
}
return 0;
}
头文件:
#pragma once
#include <iostream>
class Sales_data
{
public:
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
std::string isbn()const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price()const;
friend std::istream& operator>>( std::istream& is, Sales_data&);
friend std::ostream& operator<<(std::ostream& os, const Sales_data&) ;
};
练习7.4
#pragma once
#include <iostream>
class Person
{
public:
std::string name;
std::string address;
};
练习7.5
是const的,并不会对返回值修改.
头文件代码如下:
#pragma once
#include <iostream>
class Person
{
public:
std::string m_name;
std::string m_address;
public:
Person(std::string name, std::string address) :m_name(name), m_address(address) { }
std::string getName()const;
std::string getAddress() const;
};
源代码:
#include "person.h"
std::string Person::getName() const
{
return m_name;
}
std::string Person::getAddress() const
{
return m_address;
}
练习7.6
std::istream& read(std::istream& is, Sales_data& item)
{
int price;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
std::ostream& print(std::ostream& os, const Sales_data& item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue;
return os;
}
Sales_data add(const Sales_data& item1, const Sales_data& item2)
{
Sales_data sum(item1);
sum.combine(item2);
return sum;
}
练习7.7
Sales_data total;
if (read(cin, total))
{
Sales_data trans;
while (read(cin, trans))
{
if (total.isbn() == trans.isbn())
add(total, trans);
else
{
print(cout, total) << endl;
total = trans;
}
}
print(cout, total) << endl;
}
else
{
cerr << "No data?" << endl;
}
练习7.8
因为print并不修改其参数,所以常量引用.
练习7.9
std::istream& read(std::istream& is, Person& p)
{
is >> p.m_address >> p.m_name;
return is;
}
std::ostream& print(std::ostream& os, const Person& p)
{
os << p.getAddress() << " " << p.getName();
return os;
}
练习7.10
判断是否正确读入了data2
练习7.11
头文件
#pragma once
#include <iostream>
class Sales_data
{
public:
//构造函数,以 = default来指定默认构造函数,全部成员均使用类内初始化
// 如果某个变量未类内初始化,则出现未定义错误
Sales_data() = default;
//初始化部分成员,其余成员使用类内初始化
Sales_data(std::string id) { bookNo = id; }
//初始化部分成员,其余成员使用默认参数初始化
// *****有类内初始化了时,一般就不要用默认参数覆盖类内初始化值了***
// 可以部分成员列表初始化,部分成员在函数体内初始化
Sales_data(std::string id, unsigned sold , double rev = 0.0)
: units_sold(sold), revenue(rev)
{
bookNo = id;
}
//构造函数初始值列表
Sales_data(int n1, int n2) :units_sold(n1), revenue(n2) { }
//类外定义构造函数
Sales_data(std::istream&);
public:
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
std::string isbn()const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price()const;
friend std::istream& operator>>(std::istream& is, Sales_data&);
friend std::ostream& operator<<(std::ostream& os, const Sales_data&);
};
std::istream& read(std::istream& is, Sales_data& item);
std::ostream& print(std::ostream& os, const Sales_data& item);
Sales_data add(const Sales_data& item1, const Sales_data& item2);
测试使用:
int main()
{
Sales_data p1();
Sales_data p2("test");
Sales_data p3("test1", 1.5);
Sales_data p4(5, 20.5);
Sales_data p5(cin);
return 0;
}
练习7.12
嗯,直接放进来会报错.
练习7.13
int main()
{
Sales_data total(cin);
if (cin) {
Sales_data trans(cin);
do {
if (total.isbn() == trans.isbn())
total.combine(trans);
//.........
} while (read(cin, trans));
}//...
return 0;
}
练习7.14
Sales_data(std::string id = "", unsigned int sold = 0, double rev = 0.0)
:bookNo(id), units_sold(sold), revenue(rev) {}
练习7.15
Person() = default;
Person(std::string name, std::string address) :m_name(name), m_address(address) { }
练习7.16
类定义中,对于类中访问说明符的次数和位置均无限制.
public修饰期望在整个程序内被访问的成员,多为成员函数
private修饰可以被类的成员函数访问,但是不想被该类的代码访问到的成员,如成员变量.
练习7.17
C++语言中,class和struct的最大区别是默认访问权限不同,class默认是private,struct是public
练习7.18
把对象的实现细节隐藏起来,仅提供成员函数接口供对成员操作.作用:提高了安全性.
练习7.19
名字和地址是private的,其他是public
练习7.20
友元:类可以允许外部类或者函数访问类内非公有成员,这类类或者函数称为友元类或者友元函数.
利:外部函数也可访问类内私有成员,使得类的接口扩展更为灵活.比如,当要用到每个私有成员变量时,则需要额外定义很多个公有成员函数.
弊:在一定程度上将类的私有成员暴露出来,破坏了类的信息隐藏机制,降低了类的封装性.
练习7.21
练习7.22
以上两题相同. 把成员变量都修改为private,然后把add,print,read函数调整为友元函数即可.
练习7.23
练习7.24
#pragma once
#include <string>
class Screen
{
public:
typedef std::string::size_type pos;
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 ht, pos wd)const;
Screen& move(pos r, pos c);
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
};
inline Screen& Screen::move(pos r, pos c)
{
pos row = r * width;
cursor = row + c;
return *this;
}
练习7.25
能,string和内置类型都是拷贝和赋值安全的.
练习7.26
加个inline就行
练习7.27
按着书上来就是正确的
练习7.28
set只改变临时值得副本,不改变myScreen的contents
练习7.29
推测正确的.
练习7.30
优点:明确指出访问的是调用该函数的对象的成员
缺点:如题目所说,多余.