df# 学习目标:
掌握类的基础内容
学习内容:
1.类的简介
2.自定义数据结构
3.定义抽象数据类型
4.访问控制与封装
5.类的其他特性
6.类的作用域
7.构造函数再探
8.类的静态成员
题目解析
1.20
#include <iostream>
#include "Sales_item.h"
int main()
{
Sales_item sa;
std::cin >> sa;
std::cout << sa << std::endl;
}
1.21
#include <iostream>
#include "Sales_item.h"
int main()
{
Sales_item sa1;
Sales_item sa2;
std::cin >> sa1 >> sa2;
std::cout << sa1 + sa2 << std::endl;
}
1.22
#include <iostream>
#include "Sales_item.h"
int main()
{
Sales_item sa1;
Sales_item sum_sa2;
std::cin >> sum_sa2;
while (std::cin >> sa1)
sum_sa2 += sa1;
std::cout << sum_sa2 << std::endl;
}
1.23
#include <iostream>
#include "Sales_item.h"
int main()
{
Sales_item currItem, valItem;
if (std::cin >> currItem) {
int cnt = 1;
while (std::cin >> valItem) {
if (valItem.isbn() == currItem.isbn())
++cnt;
else {
std::cout << currItem << " occurs " << cnt << " times "
<< std::endl;
currItem = valItem;
cnt = 1;
}
}
std::cout << currItem << " occurs " << cnt << " times " << std::endl;
}
return 0;
}
1.24
测试
…
2.39
“foo”后面接“int”是非法的(是否忘记了“;”?)
main”的返回类型应为“int”而非“foo”
return”: 无法从“int”转换为“foo”
2.40
struct foo {
std::string ib;
unsigned com = 0;
double pre = 0.00;
};
2.41
#include <iostream>
#include <string>
#include "Sales_data.h"
int main()
{
Sales_data data1, data2;
double price = 0;
std::cin >> data1.bookno >> data1.units_sold >> price;
data1.revenue = data1.units_sold * price;
std::cin >> data2.bookno >> data2.units_sold >> price;
data2.revenue = data2.units_sold * price;
if (data1.bookno == data2.bookno) {
unsigned totalCnt = data1.units_sold + data2.units_sold;
double totalRevenue = data1.revenue + data2.revenue;
std::cout << data1.bookno << " " << totalCnt << " "
<< totalRevenue << " ";
if (totalRevenue != 0)
std::cout << totalRevenue/totalCnt << std::endl;
else
std::cout << "没有售出书本" << std::endl;
return 0;
}
else {
std::cerr << "不是相同书目" << std::endl;
return -1;
}
}
#include <iostream>
#include <string>
#include "Sales_data.h"
using std::cin;
int main()
{
Sales_data data1, data2;
double price1 = 0;
if (cin >> data1.bookno >> data1.units_sold >> price1)
data1.revenue = data1.units_sold * price1;
double price2 = 0;
while (cin >> data2.bookno >> data2.units_sold >> price1)
{
data2.revenue = data2.units_sold * price1;
if (data1.bookno == data2.bookno)
{
data1.units_sold += data2.units_sold;
data1.revenue += data2.revenue;
}
else
{
std::cout << data1.bookno << " " << data1.units_sold << " "
<< data1.revenue << " ";
if (data1.units_sold != 0)
std::cout << data1.revenue / data1.units_sold << std::endl;
else
std::cout << "无售出";
data1.bookno = data2.bookno;
data1.units_sold = data2.units_sold;
data1.revenue = data2.revenue;
}
}
std::cout << data1.bookno << " " << data1.units_sold << " "
<< data1.revenue << " ";
if (data1.units_sold != 0)
std::cout << data1.revenue / data1.units_sold << std::endl;
else
std::cout << "无售出";
return 0;
}
2.42
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
struct Sales_data {
std::string bookno;
unsigned units_sold = 0;
double revenue = 0.00;
};
#endif
与41题相似
7.1
见习题2.41
7.2
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
struct Sales_data {
std::string bookno;
unsigned units_sold = 0;
double revenue = 0.00;
std::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;
return *this;
}
#endif
7.3
#include <iostream>
#include <string>
#include "Sales_data.h"
int main()
{
Sales_data total;
double totalPrice;
if (std::cin >> total.bookNo >> total.units_sold >> totalPrice)
{
total.revenue = total.units_sold * totalPrice;
Sales_data trans;
double transPrice;
while (std::cin >> trans.bookNo >> trans.units_sold >> transPrice)
{
trans.revenue = trans.units_sold * transPrice;
if (total.isbn() == trans.isbn())
{
total.combine(trans);
}
else
{
std::cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " ";
if (total.units_sold != 0)
std::cout << total.revenue / total.units_sold << std::endl;
else
std::cout << "(no sales)" << std::endl;
total = trans;
}
}
std::cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " ";
if (total.units_sold != 0)
std::cout << total.revenue / total.units_sold << std::endl;
else
std::cout << "(no sales)" << std::endl;
return 0;
}
else
{
std::cerr << "No data?!" << std::endl;
return -1; // indicate failure
}
}
7.4
#pragma once
#ifndef PERSON_H
#define PERSON_H
#include <string>
struct Person {
std::string name;
std::string address;
};
#endif
7.5
使用const,只需读取成员函数的成员对象无需改变对象
#pragma once
#ifndef PERSON_H
#define PERSON_H
#include <string>
struct Person {
std::string name;
std::string address;
std::string get_name() const { return name; }
std::string get_address() const { return address; }
};
#endif
7.6
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
struct Sales_data {
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.00;
std::string isbn() const { return bookNo; }
Sales_data &combine(const Sales_data &);
double avg_price() const;
};
double Sales_data::avg_price() const {
if (units_sold)
return revenue / units_sold;
else
return 0;
}
Sales_data &Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
std::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;
}
std::ostream &print(std::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 &lsh, const Sales_data &rhs)
{
Sales_data sum = lsh;
sum.combine(rhs);
return sum;
}
#endif
7.7
#include <iostream>
#include <string>
#include "Sales_data.h"
int main()
{
Sales_data total;
double totalPrice;
if (read(std::cin, total))
{
Sales_data trans;
while (read(std::cin, trans))
{
if (total.isbn() == trans.isbn())
{
total.combine(trans);
}
else
{
print(std::cout, total);
std::cout << std::endl;
total = trans;
}
}
print(std::cout, total);
std::cout << std::endl;
return 0;
}
else
{
std::cerr << "No data?!" << std::endl;
return -1; // indicate failure
}
}
7.8
read的Sales_data参数会被修改,print不会
7.9
#pragma once
#ifndef PERSON_H
#define PERSON_H
#include <string>
struct Person {
std::string name;
std::string address;
std::string get_name() const { return name; }
std::string get_address() const { return address; }
};
std::istream &read(std::istream &is, Person &item)
{
return is >> item.name >> item.address;
}
std::ostream &print(std::ostream &os, const Person &item)
{
return os << item.name << " " << item.address;
}
#endif
7.10
输入data1和data2,判断条件是否为真
7.11
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
struct Sales_data {
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s) { }
Sales_data(const std::string &s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(p*n) { }
Sales_data(std::istream &);
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.00;
std::string isbn() const { return bookNo; }
Sales_data &combine(const Sales_data &);
double avg_price() const;
};
double Sales_data::avg_price() const {
if (units_sold)
return revenue / units_sold;
else
return 0;
}
Sales_data &Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
std::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;
}
std::ostream &print(std::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 &lsh, const Sales_data &rhs)
{
Sales_data sum = lsh;
sum.combine(rhs);
return sum;
}
#endif
7.12
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
struct 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 &lhs, const Sales_data &rhs);
struct Sales_data
{
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s) {}
Sales_data(const std::string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {}
Sales_data(std::istream &is) {read(is,*this); }
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::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;
}
std::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;
}
std::ostream &print(std::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;
}
#endif
7.13
#include <iostream>
#include <string>
#include "Sales_data.h"
int main()
{
Sales_data total (std::cin);
if (!total.isbn().empty())
{
Sales_data trans;
while (read(std::cin, trans))
{
if (total.isbn() == trans.isbn())
{
total.combine(trans);
}
else
{
print(std::cout, total);
std::cout << std::endl;
total = trans;
}
}
print(std::cout, total);
std::cout << std::endl;
return 0;
}
else
{
std::cerr << "No data?!" << std::endl;
return -1; // indicate failure
}
}
7.14
Sales_data() : bookNo(""), units_sold(0), revenue(0){}
7.15
#pragma once
#ifndef PERSON_H
#define PERSON_H
#include <string>
struct Person;
std::istream &read(std::istream &is, Person &item);
std::ostream &print(std::ostream &os, const Person &item);
struct Person {
Person() : name(" "), address(" "){}
Person (const std::string &n, const std::string &a) : name(n), address(a){}
Person(std::istream &is) { read(is, *this); }
std::string name;
std::string address;
std::string get_name() const { return name; }
std::string get_address() const { return address; }
};
std::istream &read(std::istream &is, Person &item)
{
return is >> item.name >> item.address;
}
std::ostream &print(std::ostream &os, const Person &item)
{
return os << item.name << item.address;
}
#endif
7.16
一个类可以包含0个或多个访问说明符,而且对于某个说明符能出现多少次也没有严格的限定
public成员定义类接口,private部分封装了类的实现部分。
7.17
使用struct关键字,则定义在第一个访问说明符之前的成员是public的,
相反,使用class关键字,则这些成员是private的。
7.18
含义:封装实现了类的接口和实现的分离
用处:1.确保用户代码不会无意间破坏封装对象的状态。2.被封装的类的具体实现细节可以随时改变,
而无须调整用户级别的代码。
7.19
struct Person {
public:
Person() : name(" "), address(" "){}
Person (const std::string &n, const std::string &a) : name(n), address(a){}
Person(std::istream &is) { read(is, *this); }
std::string get_name() const { return name; }
std::string get_address() const { return address; }
private:
std::string name;
std::string address;
};
接口应该是公共的所以使用public,实现的部分比如数据不应该暴露在外所以使用private。
7.20
使其允许其他类或函数访问它的非公有成员
优点:
外部函数可以方便地使用类的成员,而不需要显示地给它们加上类名;
可以方便地访问所有非公有成员;
有时,对类的用户更容易读懂。
缺点:
减少封装和可维护性;
代码冗长,类内的声明,类外函数声明。
7.21
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
struct 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 &lhs, const Sales_data &rhs);
struct Sales_data
{
friend std::istream &read(std::istream &is, Sales_data &item);
friend std::ostream &print(std::ostream &os, const Sales_data &item);
friend Sales_data add(const Sales_data &lhs, const Sales_data &rhs);
public:
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s) {}
Sales_data(const std::string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {}
Sales_data(std::istream &is) {read(is,*this); }
std::string isbn() const { return bookNo; }
Sales_data &combine(const Sales_data &);
double avg_price() const;
private:
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
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;
}
std::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;
}
std::ostream &print(std::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;
}
#endif
7.22
#pragma once
#ifndef PERSON_H
#define PERSON_H
#include <string>
struct Person;
std::istream &read(std::istream &is, Person &item);
std::ostream &print(std::ostream &os, const Person &item);
struct Person {
friend std::istream &read(std::istream &is, Person &item);
friend std::ostream &print(std::ostream &os, const Person &item);
public:
Person() : name(" "), address(" "){}
Person (const std::string &n, const std::string &a) : name(n), address(a){}
Person(std::istream &is) { read(is, *this); }
std::string get_name() const { return name; }
std::string get_address() const { return address; }
private:
std::string name;
std::string address;
};
std::istream &read(std::istream &is, Person &item)
{
return is >> item.name >> item.address;
}
std::ostream &print(std::ostream &os, const Person &item)
{
return os << item.name << item.address;
}
#endif
7.23
#pragma once
#ifndef SCREEN_H
#define SCREEN_H
#include <iostream>
#include <string>
class Screen {
public:
typedef std::string::size_type pos;
Screen() = default;
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;
}
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
#endif
7.24
Screen() = default;
Screen(pos ht, pos wd) : height(ht), width(wd){}
Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c){}
7.25
能,Screen类中只有内置类型和string,这些能使用默认版本
7.26
//类外
inline double Sales_data::avg_price() const {
if (units_sold)
return revenue / units_sold;
else
return 0;
}
//或类内显式或隐式
inline double Sales_data::avg_price() const
double Sales_data::avg_price() const
###补充关于const的相关记忆
int i = 0; const int ci = 0; //int const ci = 0
int &g = i; const int &g = i; //int const &g = i; // &后面应是标识符
int &cg = ci; const int &cg = ci;
int *p = &i; const int *p = &i; // int const *p = &i;
int *cp = &ci; const int *cp = &ci;
int *const cpp = &i; const int *const cpp = &i; // int const *const cpp = &i; // *const后面应是标识符
int *const cpp = &ci; const int *const cpp = &ci;
int i = 0;
//顶层const,不能修改地址,本身是常量
int *const p1 = &i; //
const int ci = 42;
//底层const,不能修改地址和值,本身不是常量,指向的对象是常量
//拷出的对象要是底层const,拷入的对象能转换成底层const
const int *p2 = &ci;
const int &r = ci;
7.27
#pragma once
#ifndef SCREEN_H
#define SCREEN_H
#include <iostream>
#include <string>
class Screen {
public:
typedef std::string::size_type pos;
Screen &set(char);
Screen &set(pos, pos, char);
Screen() = default;
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);
Screen &display(std::ostream &os) { do_display(os); return *this; }
const Screen &display(std::ostream &os) const { do_display(os); return *this; }
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
void do_display(std::ostream &os) const { os << contents; }
};
inline Screen &Screen::move(pos r, pos c)
{
pos row = r * width;
cursor = row + c;
return *this;
}
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
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;
}
#endif
#include <string>
#include <iostream>
#include "SCREEN.H"
int main()
{
Screen myScreen(5, 5, 'X');
myScreen.move(4, 0).set('#').display(std::cout);
std::cout << "\n";
myScreen.display(std::cout);
std::cout << "\n";
return 0;
}
7.28
7.29
7.30
7.31
class X {
Y *y = nullptr;
};
class Y {
X x;
};
7.32
#ifndef SCREEN_H_
#define SCREEN_H_
#include <string>
#include <vector>
class Screen;
class Window_mgr
{
public:
using ScreenIndex = std::vector<Screen>::size_type;
void clear(ScreenIndex);
private:
std::vector<Screen> screens;
};
class Screen
{
friend void Window_mgr::clear(ScreenIndex);
public:
using pos = std::string::size_type;
Screen() = default;
Screen(pos ht, pos wd):height(ht), width(wd){ }
Screen(pos ht, pos wd, char c):height(ht), width(wd), contents(ht*wd, c){ }
char get() const { return contents[cursor]; }
char get(pos r, pos c) const { return contents[r*width+c]; }
Screen &move(pos r, pos c);
Screen &set(char);
Screen &set(pos, pos, char);
Screen &display(std::ostream &os) {do_display(os); return *this;}
const Screen &display(std::ostream &os) const {do_display(os); return *this;}
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
void do_display(std::ostream &os) const {os << contents;}
};
inline 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 c)
{
contents[r*width + col] = c;
return *this;
}
void Window_mgr::clear(ScreenIndex i)
{
Screen &s = screens[i];
s.contents = std::string(s.height * s.width, ' ');
}
#endif
7.33
#pragma once
#ifndef SCREEN_H
#define SCREEN_H
#include <iostream>
#include <string>
#include "Window_mgr.h"
class Screen {
friend void Window_mgr::clear(ScreenIndex);
public:
typedef std::string::size_type pos;
Screen &set(char);
Screen &set(pos, pos, char);
Screen() = default;
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);
Screen &display(std::ostream &os) { do_display(os); return *this; }
const Screen &display(std::ostream &os) const { do_display(os); return *this; }
pos size() const;
private:
pos cursor = 0;
pos height = 0, width = 0;
std::string contents;
void do_display(std::ostream &os) const { os << contents; };
};
inline Screen &Screen::move(pos r, pos c)
{
pos row = r * width;
cursor = row + c;
return *this;
}
char Screen::get(pos r, pos c) const
{
pos row = r * width;
return contents[row + c];
}
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;
}
Screen::pos Screen::size() const
{
return height * width;
}
#endif
7.34
会报错,内部声明是有顺序的
7.35
#include <string>
typedef std::string Type;
Type initVal(); // 全局的
class Exercise {
public:
typedef double Type;
Type setVal(Type); // 两者都是类内的
Type initVal(); // 类内的
private:
int val;
};
Type Exercise::setVal(Type parm) { // 前者是全局,后者是类内的
val = parm + initVal(); // 类内的
return val;
}
//改
//Exercise::Type Exercise::setVal(Type parm) { // 前者是全局,后者是类内的
// val = parm + initVal();
// return val;
//}
7.36
改变rem,base的顺序
int base,rem;
7.37
Sales_data first_item(cin); // use Sales_data(std::istream &is) ; its value are up to your input.
int main() {
Sales_data next; // use Sales_data(std::string s = ""); bookNo = "", cnt = 0, revenue = 0.0
Sales_data last("9-999-99999-9"); // use 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
非法,两个以上默认构造函数,重载构造函数不明确
7.40
#pragma once
#ifndef BOOK_H
#define BOOK_H
#include <iostream>
#include <string>
class Book
{
public:
Book(unsigned isbn, std::string const &name, std::string const &author, std::string const &pubdate)
:isbn_(isbn), name_(name), author_(author), pubdate_(pubdate)
{ }
explicit Book(std::istream &in)
{
in >> isbn_ >> name_ >> author_ >> pubdate_;
}
private:
unsigned isbn_;
std::string name_;
std::string author_;
std::string pubdate_;
};
#endif
7.41
#pragma once
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
#include <iostream>
struct 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 &lhs, const Sales_data &rhs);
struct Sales_data
{
friend std::istream &read(std::istream &is, Sales_data &item);
friend std::ostream &print(std::ostream &os, const Sales_data &item);
friend Sales_data add(const Sales_data &lhs, const Sales_data &rhs);
public:
Sales_data(const std::string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p *n) { std::cout << "s,n,p" << std::endl; }
Sales_data(const std::string &s) : Sales_data(s, 0, 0) { std::cout << "Sales_data(s)" << std::endl; }
Sales_data() : Sales_data("", 0, 0) { std::cout << "Sales()" << std::endl; }
Sales_data(std::istream &is) : Sales_data() {read(is,*this); }
std::string isbn() const { return bookNo; }
Sales_data &combine(const Sales_data &);
inline double avg_price() const;
private:
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
Sales_data &Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
inline double Sales_data::avg_price() const {
if (units_sold)
return revenue / units_sold;
else
return 0;
}
std::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;
}
std::ostream &print(std::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;
}
#endif
7.42
Book(unsigned isbn, std::string const &name, std::string const &author, std::string const &pubdate)
:isbn_(isbn), name_(name), author_(author), pubdate_(pubdate)
{ }
可以作为委托构造函数,因为处理的信息量足够
7.43
#include <string>
class NoDefault {
public:
NoDefault(int i) {};
};
struct C {
public:
C() : de(0) {};
private:
NoDefault de;
};
7.44
合法
7.45
合法
7.46
(a)不正确,没有构造函数时,编译器会生成一个默认构造函数
(b)不正确,也有参数的默认构造函数其参数是默认值
(c)不正确,默认构造函数有时很重要
(d)不正确,当类没有显式构造函数时,编译器才会生成一个合成的默认构造函数
7.47
不是,这样方便我们进行转换
优点:
防止隐式转换的产生;
可以只用作初始化。
缺点:
只有个单个参数的构造函数才有意义。
7.48
不是explicit的:
string类型
Sales_data临时量类型
Sales_data临时量类型
是explicit
string类型
Sales_data临时量类型
Sales_data临时量类型
7.49
7.50
explicit Person(std::istream &is) { read(is, *this); }
7.51
这里直接调用参数是vector的get的一个实参数值会报错,因为函数不知道这个数是容器大小还是容器的第一个值
int get(const std::vector<int> &);
get(12);
这里形参换成string就不会
int get2(const std::string &);
get2("ds");
7.52
聚合类要求没有类内初始值,程序应该改成
struct Sales_data {
std::string bookNo;
unsigned units_sold;
double revenue;
};
7.53
#ifndef DEBUG_EX53_
#define DEBUG_EX53_
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(o) {}
constexpr bool any() { return hw || io || other; }
void set_io(bool b) { io = b; }
void set_hw(bool b) { hw = b; }
void set_other(bool b) { other = b; }
private:
bool hw;
bool io;
bool other;
};
#endif
7.54
constexpr函数是隐式的const。
7.55
不是,有一个string类型的数据成员所以不是字面值常量类。
7.56
类的静态成员是和类绑定的成员,但是不和类的对象绑定
优点:可以直接调整对象,数据成员非法的地方静态成员可以替代
区别:数据成员的作用域在类内,静态成员的作用域在类外
7.57
#ifndef ACCOUNT_EX57_H_
#define ACCOUNT_EX57_H_
#include <string>
class Account
{
public:
void calculate() {amount += amount * interestRate;}
static double rate(){return interestRate;}
static void rate(double newRate){ interestRate = newRate;}
private:
std::string owner;
double amount;
static double interestRate;
static double initRate(){return 4.0;}
};
double Account::interestRate = initRate();
#endif
7.58
//example.h
#include <vector>
class Example {
public:
static double rate = 6.5; //成员必须为常量
static const int vecSize = 20;
static std::vector<double> vec(vecSize); //vecSize是在类外声明的
};
//example.c
double Example::rate;
std::vector<double> Example::vec; //静态成员只能定义一次
改
//example.h
#include <vector>
class Example {
public:
static double rate;
static const int vecSize = 20;
static std::vector<double> vec;
};
//example.c
double Example::rate = 6.5;
std::vector<double> Example::vec(vecSize);