C++Primer练习[第二章]

//2.1 类型int 、long 、longlong 和short的区别是什么?
//无符号类型和带符号类型的区别是什么?
//float和double的区别是什么?
//答:类型int 、long 、longlong 和short的区别是占的比特数不同,所能表示的数据范围也不一样。
//无符号类型和带符号类型的区别是带符号类型可以表示正数、负数或0,无符号类型则仅能表示大于等于0的值。带符号类型有一位用来表示正负号,而无符号类型中所有比特都用来存储值。
//float以一个字来表示,有7个有效位。double以两个字来表示,有16个有效位


//2.2 计算按揭贷款,对于利率,本金,和付款分别选择何种数据类型,说明理由
//答:利率、本金用float类型,因为利率一般精确到小数点后4位,本金为小数点后2位,付款是本金*利率,应该要多点有效位。所以付款使用double.


//2.3读程序写结果
//
//unsigned u = 10, u2 = 42;
//std::cout << u2 - u << std::endl;
//std::cout << u - u2 << std::endl;
//
//int i = 10, i2 = 42;
//std::cout << i2 - i << std::endl;
//std::cout << i - i2 << std::endl;
//std::cout << i - u << std::endl;
//std::cout << u - i << std::endl;
//答:32
//4294967264
//32
//-32
//0
//0


//2.4 编写程序检查你的估计是否正确,如果不正确,请仔细读本节知道弄明白问题所在。
//无符号数始终大于等于0,把负数转换成无符号数结果等于这个负数加上无符号数的模。
#include <iostream>

int main()
{
unsigned u = 10, u2 = 42;
std::cout << u2 - u << std::endl;
std::cout << u - u2 << std::endl;

int i = 10, i2 = 42;
std::cout << i2 - i << std::endl;
std::cout << i - i2 << std::endl;
std::cout << i - u << std::endl;
std::cout << u - i << std::endl;

system("pause");
return 0;
}


//2.5指出下述字面值的数据类型并说明每一组内几种字面值的区别
//(a)'a',L'a',"a",L"a"
//(b)10,10u,10L,10uL,012,0xC
//(c)3.14,3.14f,3.14L
//(d)10,10u,10.,10e-2
//答:(a)'a'为字符型字面值,类型是char 
//L'a'为宽字符型字面值,类型是wchar_t
//"a"为字符串型字面值,类型是char*
//L"a"为宽字符串型字面值,类型是wchar_t*
//区别:char ascii编码 用于处理单个字符,wchar unicode编码 用于处理中文等字符
//(b)10为整型十进制字面值,类型是int
//10u为无符号整型十进制字面值,类型是unsigned int
//10L为整型十进制字面值,类型是long int
//012为整型八进制字面值,类型是int或unsingned int
//0xC为整型十六进制字面值,类型是int或unsingned int
//区别:后缀不同,类型也不同,存储值范围不同。
//(c)3.14为浮点型字面值,类型是double
//3.14f为单精度浮点型字面值,类型是float
//3.14L为扩展精度浮点型字面值,类型是long double
//区别:后缀不同,类型也不同,存储值范围不同。
//(d)10为整型十进制字面值,类型是int
//10u为无符号整型十进制字面值,类型是unsigned int
//10.为浮点型字面值,类型是double
//10e-2为浮点型字面值,类型是double
//区别:整型和浮点型类型不同,存储值范围不同。


//2.6下面两组定义是否有区别,如果有,请叙述之:
//int month = 9,day = 7;
//int month = 09, day = 07;
//答:有区别,一个是用十进制表示,一个是用八进制表示,int month = 09有误,应写做int month = 011


//2.7 下述字面值表示何种含义,他们各自的数据类型是什么?
//(a) “who goes with F\145rgues?\012”
//(b) 3.14e1L
//(c) 1024f
//(d) 3.14L
//答:(a)字符串字面值,char*
//(b)扩展精度浮点型字面值,long double
//(c)单精度浮点型字面值,float
//(d)扩展精度浮点型字面值,long double


//2.8 请用转义序列编写一段程序,要求先输出2M, 然后转到新一行。修改程序使其输出2,然后输出制表符,在输出M,最后转到新一行。
#include <iostream>

int main()
{
std::cout << "2M\n2\tM\n";

system("pause");
return 0;
}


//2.9 解释下列定义的含义。对于非法的定义,请说明错在何处并将其改正
//(a) std::cin>>int input_value;
//(b) int i = { 3.14 };
//(c) double salary = wage = 9999.99;
//(d) int i = 3.14;
//答:(a)非法定义。变量要先定义再使用。
//int input_value;
//std::cin >> input_value;
//(b) 非法定义,因为存在丢失信息的风险。
//(c) 非法定义,wage未定义
//double salary, wage
//salary = wage = 9999.99; 
//(d) 定义int类型的变量,变量名为i,给i初始化值为3.14(但是i初始化后的值为3,小数部分会丢失)


//2.10 下列变量的初值分别是什么?
//std::string global_str;
//int global_int;
//int main()
//{
// int local_int;
// std::string local_str;
//}
//答:global_str的初值为空字符串,
//global_int的初值为0(因为内置类型被定义于任何函数体之外的变量被初始化为0),
//local_int的初值未被初始化,未定义(定义在函数体内部的内置类型变量将不被初始化,其值是未定义的),
//local_str的初值为空字符串


//2.11 指出下面的语句是声明还是定义:
//(a) extern int ix = 1024;
//(b) int iy;
//(c) extern int iz;
//答:(a)定义。任何包含了显示初始化的声明即成为定义。
//(b) 声明并定义。
//(c) 声明。


//2.12 请指出下面的名字中哪些是非法的?
//(a) int double = 3.14;
//(b) int _;
//(c) int catch-22;
//(d) int 1_or_2 = 1;
//(e) double Double = 3.14;
//答:(a)非法。double为C++关键字。C++关键字、保留名字不能被用作标识符。
//(b)合法
//(c)非法,标识符由字母、数字和下划线组成,其中必须以字母或下划线开头。-号不能用于标识符。
//(d)非法,不能以数字开头。
//(e)合法。


//2.13 下面程序中j的值是多少 ?
//
//int i = 42;
//int main()
//{
// int i = 100;
// int j = i;
//}
//答:100


//2.14 下面程序合法吗?如果合法?它将输出什么?
//
//int i = 100, sum = 0;
//for (int i = 0; i != 10; ++i)
// sum += i;
//std::cout << i << " " << sum << std::endl;
//答:合法。100 45




//2.15: 下面的那个定义是不合法的?为什么?
//
//(a) int ival = 1.01;
//(b) int &rvall = 1.01;
//(c) int &rval2 = ival;
//(d) int &rval3;
//答:(a)合法
//(b) 不合法。引用类型的初始值必须是一个对象,而不能是字面值或者某个表达式的计算结果
//(c) 若ival是一个已定义的int型变量,是合法的。否则不合法。
//(d) 不合法。引用必须初始化。定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另外一个对象,因此引用必须初始化。


//2.16 考查下面的所有赋值然后回答:哪些赋值是不合法的?为什么?哪些赋值是合法的?它们执行了什么样的操作?
//
//int i = 0, &r1 = i; double d = 0, &r2 = d;
//(a) r2 = 3.14159;
//(b) r2 = r1;
//(c) i = r2;
//(d) r1 = d;
//答:(a)合法。相当于将值3.14159赋给d
//(b)合法。相当于将i(0)赋给d
//(c)合法。相当于将d的值赋给i,但是精度会丢失
//(d)合法。相当于将d的值赋给i,但是精度会丢失


//2.17 执行下面的代码段将输出什么结果 ?
//
//int i, &ri = i;
//i = 5; ri = 10;
//std::cout << i << " " << ri << std::endl;
//答:10 10


//2.18 编写代码分别更改指针的值以及指针所指对象的值。
#include <iostream>

int main()
{
int *p = nullptr;
int ival = 0;
p = &ival; //改变指针的值
*p = 100;//改变指针所指对象的值


system("pause");
return 0;
}


//2.19 说明指针和引用的主要区别
//答:引用是一个对象的别名,不是对象。引用只能在初始化的时候绑定一次,且必须初始化。
//指针是一个对象。指针所指的对象可以变化。可以不必初始化。


//2.20 请叙述下面这段代码的作用。
//
//int i = 42;
//int *p1 = &i;
//*p1 = *p1 * *p1;
//答:声明并定义一个int类型的变量i,初始化值为42;声明并定义一个int类型的指针p1,初始化指向对象i。改变p1所指对象的值为p1所指对象的值乘以p1所指对象的值(即对i赋值42x42)


//2.21 请解释下述定义。在这些定义中有非法的吗?如果有,为什么?
//
//int i = 0;
//(a)double *dp = &i;
//(b)int *ip = i; 
//(c)int *p = &i;
//答:(a)非法。指针dp的类型和int型对象地址的类型不匹配。
//(b)非法。不能把int变量直接赋值给指针
//(c)合法。


//2.22 假设p是一个int型指针,请说明下述代码的含义
//
//if (p) //.. 
//if (*p) //… 
//答:if (p) 为判断指针p是否不为空指针(即p所指的地址是否存在)
//if (*p) 为判断指针p所指的对象值是否不为0


//2.23 给定指针p,你能知道它是否指向了一个合法的对象吗? 如果能,叙述判断的思路;如果不能,也请说明原因。
//答:不能。因为指针只是指向了一个地址,这个地址上是否有存在合法的对象是不确定的。


//2.24 在下面这段代码中为什么p合法而lp非法 ?
//
//int i = 42; void *p = &i; long *lp = &i;
//答:因为void*是一种特殊的指针类型,可用于存放任意对象的地址。lp的类型和i的地址类型不匹配


//2.25 说明下列变量的类型和值。
//(a) int * ip, i, &r = i;
//(b) int i, *ip = 0;
//(c) int* ip, ip2;
//答:(a)ip是int型指针,值不确定。i是int型,值不确定。r是int型引用,是i的别名,值不确定。
//(b)i是int型,值不确定。ip是int型指针,是个空指针,存放地址为空。
//(c)ip是int型指针,值不确定。ip2是int型,值不确定


//2.26 下面那些句子是合法的?如果有不合法的句子,请说明为什么?
//
//(a)const int buf;        (b)int cnt = 0;
//(c)const int sz = cnt;   (d)++cnt; ++sz;
//答:(a)不合法。常量必须初始化。因为const对象一旦创建后其值就不能再改变,所以const对象必须初始化。
//(b)合法
//(c)合法
//(d)不合法。const对象一旦创建后其值就不能再改变。


//2.27 下面的哪些初始化是合法的?请说明原因。
//
//(a) int i = -1, &r = 0;
//(b) int *const p2 = &i2;
//(c) const int i = -1, &r = 0; 
//(d) const int *const p3 = &i2;
//(e) const int *p1 = &i2;   
//(f) const int &const r2;
//(g) const int i2 = i, &r = i;
//答:(a)i合法,r不合法。引用类型的初始值必须是一个对象(对const的引用除外)。
//(b)如果i2是个int类型对象是合法的。否则不合法。因为p2是个指向int类型的常量指针。
//(c)合法。
//(d)如果i2是个可以转换成int类型的对象是合法的。因为p3是个指向int常量类型的常量指针。
//(e)如果i2是个int类型对象或者int常量类型的对象是合法的。
//(f)不合法。没有初始化。因为r2是个对const int对象的引用。引用类型必须初始化。
//(g)如果i是个int类型对象或者int常量类型的对象是合法的。


//2.28 说明下面的这些定义是什么意思,挑出其中不合法的。
//
//(a) int i, *const cp;
//(b) int *p1, *const p2;
//(c) const int ic, &r = ic;
//(d) const int *const p3;
//(e) const int *p;
//答:(a)i是整型变量,cp是指向整型变量的常量指针。cp不合法,因为常量指针必须初始化。
//(b) p1是指向整型变量的指针,p2是指向整型变量的常量指针。p2不合法,因为常量指针必须初始化。
//(c) ic是整型常量,r是对整型常量的引用。ic不合法,因为整型常量必须初始化。
//(d) p3是指向整型常量的常量指针。p3不合法。因为常量指针必须初始化。
//(e) p是指向整型常量的指针。合法。


//2.29 假设已有上一个练习中定义的那些变量,则下面的哪些语句是合法的?请说明原因。
//
//(a)i = ic;
//(b)p1 = p3;
//(c)p1 = ⁣ &ic;
//(d)p3 = ⁣&ic;
//(e)p2 = p1; 
//(f)ic = *p3;
//答:(a)合法。可以对整型变量进行赋值。
//(b)不合法。不能将整型指针指向整型常量
//(c)不合法。不能将整型指针指向整型常量
//(d)p3是常量指针,值不能改变。
//(e)p2是常量指针,值不能改变。
//(f)p2是整型常量,值不能改变。


//2.30 对于下面的这些语句,请说明对象被声明成了顶层const还是底层const.
//
//const int v2 = 0;  int v1 = v2;
//int *p1 = &v1, &r1 = v1;
//const int *p2 = &v2, *const p3 = &i, &r2 = v2; 
//答:v2顶层const,p2底层const, p3既有顶层const又有底层const,r2底层const.


//2.31 假设已有上一个练习中所做的那些声明,则下面的那些语句是合法的?
//请说明顶层const和底层const在每个例子中有何体现。
//r1 = v2; 
//p1 = p2; p2 = p1;
//p1 = p3;p2 = p3;
//答:r1 = v2;合法。
//p1 = p2;不合法,p2包含底层const的定义,而p1没有。p2 = p1;合法,int*能转换成const int*。
//p1 = p3;不合法,p3包含底层const的定义,而p1没有。p2 = p3;合法。


//2.32 下面代码是否合法,如果非法,请设法将其修改正确
//int null = 0, *p = null;
//答:不合法。
//int null = 0, *p = &null;
//constexpr int null = 0;int *p = null;
//int null = 0, *p = nullptr;


//2.33 利用本节定义的变量,判断下列语句的运行结果。
//a = 42; b = 42; c = 42;
//d = 42; e = 42; g = 42;
//答:a是一个整数。a = 42;合法。a的值改变为42
//b是一个整数,b = 42;合法。b的值改变为42
//c是一个整数,c = 42;合法。c的值改变为42
//d是一个整型指针,d = 42;不合法。不能把常数赋值给指针。
//e是一个指向整数常量的指针(const int*). e = 42;不合法。不能把常数赋值给指针。
//g是一个整型常量引用(const int &).g = 42;不合法。不能给常量赋值。


//2.34 基于上一个练习中的变量和语句编写一段程序,输出赋值前后变量的内容,你刚才的推断正确吗?
//如果不对,请反复研读本节的示例直到你明白错在何处为止。
#include <iostream>
using namespace std;
int main()
{
int i = 0, &r = i;
auto a = r;
const int ci = i, &cr = ci;
auto b = ci;
auto c = cr;
auto d = &i;
auto e = &ci;
auto &g = ci;

a = 42; b = 42; c = 42;
d = 42; e = 42; g = 42;
cout << a << " "<< b << " " << c << " " << d << " " << e << " " << g << " " << endl;
system("pause");
return 0;
}


#include <iostream>
using namespace std;
int main()
{
int i = 0, &r = i;
auto a = r;
const int ci = i, &cr = ci;
auto b = ci;
auto c = cr;
auto d = &i;
auto e = &ci;
auto &g = ci;

a = 42; b = 42; c = 42;
//d = 42; e = 42; g = 42;
cout << a << " "<< b << " " << c << " " << d << " " << e << " " << g << " " << endl;
system("pause");
return 0;

}



//2.35 判断下列定义推断出的类型是什么,然后编写程序进行验证。
//const int i = 42;
//auto j = i;  const auto &k = i; auto *p = &i; 
//const auto j2 = i, &k2 = i; 
//答:j推断出的类型是int. int j = i;
//k推断出的类型是int. const int &k = i;
//p推断出的类型是const int. const int *p = &i;
//j2推断出的类型是int. const int j2 = i
//k2推断出的类型是int. const int &k2 = i;
#include <iostream>
using namespace std;
int main()
{
const int i = 42;
auto j = i;  const auto &k = i; auto *p = &i; 
const auto j2 = i, &k2 = i; 
cout << typeid(j).name()<< " "
<< typeid(k).name()<< " " 
<< typeid(p).name()<< " " 
<< typeid(j2).name() << " " 
<< typeid(k2).name() << " " 
<< endl;
system("pause");
return 0;
}


//2.36 关于下面的代码,请指出每一个变量的类型以及程序结束时他们各自的值
//
//int a = 3, b = 4; 
//decltype(a) c = a; 
//decltype((b)) d = a; 
//++c; 
//++d; 
//答:a的类型是int,结束时值为4
//b的类型是int,结束时值为4
//c的类型是int,结束时值为4
//d的类型是int &,结束时值为4


//2.37 赋值是会产生引用的一类型表达式,引用的类型就是左值的类型。
//也就是说,如果i是int,则表达式i=x的类型是int&。
//根据这一特点,请指出下面的代码每一个变量的类型和值
//int a = 3, b = 4;
//decltype(a) c = a; 
//decltype(a = b) d = a; 
//答:a的类型是int,值为3
//b的类型是int,值为4
//c的类型是int, 值为3
//d的类型是int&,值为3


//2.38 说明由decltype指定类型和由auto指定类型有何区别.
//请举出一个列子,decltype指定的类型与auto指定的类型一样;
//再举一个列子,decltype指定的类型与auto指定的类型不同。
//答:区别:1.decltype处理顶层const和引用的方式与auto有些许不同,
//如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内)
//2.decltype和auto的另一处重要区别是,decltype的结果类型与表达式形式密切相关。
//对于decltype所用的表达式来说,如果变量名加上了一对括号,则得到的类型与不加括号时会有不同。
//如果decltype使用的是一个不加括号的变量,则得到的结果就是该变量的类型;如果给变量加上了一层或多层括号,编译器就会把它当成是一个表达式。变量是一种可以作为赋值语句左值的特殊表达式,所以这样的decltype就会得到引用类型。
//例子1:int i;decltype(i) a = i;auto b = i;
//例子2: int i,&j=i;decltype(j) a = j;auto b = j;


//2.39 编译下面的程序观察其运行结果,注意如果忘记类定义体后面的分号会发生什么情况?记录下相关信息,以后可能会有用。
//struct Foo { /* 此处为空 */ } //注意这里没有分号 
//int main()
//{
// return 0;
//}
//答:会报错。


//2.40 根据自己的理解写出Sales_data类 最好与书中的例子有所区别。
//答:
//struct Sales_data
//{
// std::string bookNo;
// unsigned units_sold = 0;
// double revenue = 0;
// double price = 0.0f;//单价
//};


//2.41使用自己的Sales_data 类重写1.5.1节(第20页)、1.5.2节(第21页)和1.6节(第22页)的练习.
//眼下先把Sales_data和main函数放在同一个文件。
#include <iostream>
#include <string>
using namespace std;
struct Sales_data
{
std::string bookNo; //isbn
unsigned units_sold = 0; //销量
double revenue = 0; //总价
double price = 0.0f; //单价
};


int main()
{
//2.41-1 读取一组书籍销售记录,将每条记录打印到标准输出上。
Sales_data book;
while (std::cin >> book.bookNo >> book.units_sold >> book.price )
{
book.revenue = book.units_sold * book.price;
std::cout << book.bookNo << " " << book.units_sold << " " << book.revenue << " " << book.price << " "  << std::endl;
}
system("pause");
return 0;
}



int main()
{
//2.41-2 编写程序,读取两个ISBN相同的Sales_item对象,输出它们的和
Sales_data book1, book2;
std::cout << "请输入两个ISBN相同的销售记录" << std::endl;
std::cin >> book1.bookNo >> book1.units_sold >> book1.price;
std::cin >> book2.bookNo >> book2.units_sold >> book2.price;
while (book1.bookNo != book2.bookNo)
{
std::cout << "请输入两个ISBN相同的销售记录" << std::endl;
std::cin >> book1.bookNo >> book1.units_sold >> book1.price;
std::cin >> book2.bookNo >> book2.units_sold >> book2.price;
}
book1.revenue = book1.units_sold * book1.price;
book2.revenue = book2.units_sold * book2.price;
std::cout << "总和:" << book1.bookNo << " " << book1.units_sold + book2.units_sold << " " << book1.revenue + book2.revenue << " " << ((book1.revenue + book2.revenue)/(book1.units_sold + book2.units_sold)) << " " << std::endl;
system("pause");
return 0;
}



int main()
{
//2.41-3 编写程序,读取多个具有相同ISBN的销售记录,输出所有记录之和
Sales_data book;
Sales_data sum_book;
std::cout << "请输入ISBN相同的销售记录" << std::endl;
if (std::cin >> book.bookNo >> book.units_sold >> book.price)
{
book.revenue = book.units_sold * book.price;
sum_book.bookNo = book.bookNo;
sum_book.units_sold = book.units_sold;
sum_book.revenue = book.revenue;
sum_book.price = book.price;
std::cout << "请输入ISBN相同的销售记录" << std::endl;
while (std::cin >> book.bookNo >> book.units_sold >> book.price)
{
if (book.bookNo == sum_book.bookNo)
{
book.revenue = book.units_sold * book.price;
sum_book.units_sold += book.units_sold;
sum_book.revenue += book.revenue;
std::cout << "请输入ISBN相同的销售记录" << std::endl;
}
else
{
std::cout << "请输入ISBN相同的销售记录" << std::endl;
}
}
std::cout << "总和:" << sum_book.bookNo << " " << sum_book.units_sold << " " << sum_book.revenue << " " << (sum_book.revenue/ sum_book.units_sold) << " " << std::endl;
}
else
{
std::cerr << "没有数据" << std::endl;

return -1;

}

system("pause");
return 0;
}



int main()
{
//2.41-4 编写程序,读取多条销售记录,并统计每个ISBN(每本书)有几条销售记录
Sales_data book, currbook;
int count = 0;
std::cout << "请输入销售记录" << std::endl;
if (std::cin >> book.bookNo >> book.units_sold >> book.price)
{
book.revenue = book.units_sold * book.price;
currbook.bookNo = book.bookNo;
currbook.units_sold = book.units_sold;
currbook.revenue = book.revenue;
currbook.price = book.price;
count = 1;
std::cout << "请输入销售记录" << std::endl;
while (std::cin >> book.bookNo >> book.units_sold >> book.price)
{
if (currbook.bookNo == book.bookNo)
{
count++;
}
else
{
std::cout << currbook.bookNo << "有" << count << "条记录" << std::endl;
book.revenue = book.units_sold * book.price;
currbook.bookNo = book.bookNo;
currbook.units_sold = book.units_sold;
currbook.revenue = book.revenue;
currbook.price = book.price;
count = 1;
}
std::cout << "请输入销售记录" << std::endl;
}
std::cout << currbook.bookNo << "有" << count << "条记录" << std::endl;
}
else
{
std::cerr << "没有数据" << std::endl;
return -1;
}

system("pause");
return 0;
}


int main()
{
//2.41-5 编译并运行书店程序
//保持下一条交易记录的变量
Sales_data total;
//读入第一条交易记录,并确保有数据可以处理
if (std::cin >> total.bookNo >> total.units_sold >> total.price)
{
total.revenue = total.units_sold * total.price;
//保持和的变量
Sales_data trans;
//读入并处理剩余交易记录
while (std::cin >> trans.bookNo >> trans.units_sold >> trans.price)
{
trans.revenue = trans.units_sold * trans.price;
//如果我们仍在处理相同的书
if (total.bookNo == trans.bookNo)
{
//更新总销售量
total.revenue += trans.revenue;
total.units_sold += trans.units_sold;
}
else
{
//打印前一本书的结果
std::cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " " << (total.revenue / total.units_sold) << " " << std::endl;
//total现在表示下一本书的销售额
trans.revenue = trans.units_sold * trans.price;
total.bookNo = trans.bookNo;
total.units_sold = trans.units_sold;
total.revenue = trans.revenue;
total.price = trans.price;
}
}
//打印最后一本书的结果
std::cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " " << (total.revenue / total.units_sold) << " " << std::endl;
}
else
{
//没有输入!警告读者
std::cerr << "No Data?!" << std::endl;
//表示失败
return -1;
}

system("pause");

return 0;
}


//2.42 根据你自己的理解重写一个Sales_data.h头文件,并以此为基础重做2.6.2节(第67页)的练习

#ifndef __SALES_DATA
#define __SALES_DATA
#include <string>
struct Sales_data
{
std::string bookNo; //isbn
unsigned units_sold = 0; //销量
double revenue = 0; //总价
double price = 0.0f; //单价
};
#endif
//重写只需要将上面练习的struct定义删掉,并#include "Sales_data.h"即可。

猜你喜欢

转载自blog.csdn.net/sukeychen/article/details/80309379