发现前面的笔记格式不是很好,后面会慢慢注意!
知识点:
1. 构造函数不能被声明成const。当创建类的一个const对象时,直到构造函数完成初始化过程,对象才能真正取得其“常量”属性。所以,构造函数在const对象的构造过程中可以向其写值。
2. 在C++11新标准中,如果我们需要默认的行为,那么可以通过在参数列表后面写上 = default 来要求编译器生产构造函数,其既可以出现在类内(内联),也可以出现在类外。
3. 构造函数初始值列表:它负责为新创建的对象的一个或几个数据成员赋初值,当某个数据成员被构造函数初始值列表忽略时,它将由编译器进行隐式初始化。
4. 尽管编译器能替自动合成拷贝,赋值和销毁的操作。但是,当类需要分配类对象之外的资源时,合成的版本常常失效(浅拷贝)。
5. 友元声明只能出现在类定义的内部,但是在类内出现的具体位置不限。友元不是类的成员也不受它所在区域访问控制级别的约束。
6.友元的声明仅仅指定了访问的权限,而非一个通常意义上的函数声明。如果用户要调用某个友元函数,必须在友元声明之外再专门对函数进行一次声明。(一些编译器支持不用额外声明)
7.
在变量前加关键字mutable,变为可变数据成员,即使是在一个const的对象函数中也可以被修改。
8.
C++11 之前的标准是不允许在类内初始化非静态数据成员的,只有静态常量整型数据成员,才可以在类中初始化。具体原因可以看下列原因(旧 版):习题7_23
(1)
类只是一个抽象类型,并不是实体的东西,利用这个抽象类型会实例化成不同的个体,每个个体的特征(数据成员)都不一样,如果在类定义中将特征初始化了,岂不是破坏了抽象性,做了一个面向都一样的模子?
(2)
类的定义实际相当与类型声明,并没有分配存储空间,初始化的数据哪里放? 类实例化以后才会有实体存储地址及空间。
习题:
7.16 答:没有限定 访问级别直到下一个访问说明符或类主体结束时。设计能被外部访问的应该是public修饰,而隐藏细节被封装的但能被成员函数访问的应该被private修饰。
7.17 答:calss默认访问说明符是private,struct默认是public,仅此而已。
7.18 答:封装是将用户代码及可能影响到类或程序进行了权限控制。实现了类的接口和类的实现的分离,限制了不合理的操作,提高安全性,隐藏了类的实现细节。
7.19 答:之前编写全部按public练习了。学习本节后接口函数声明成 public,可供外部访问; 成员变量声明private,相关数据隐藏,对类外屏蔽。
7.20 答:友元可以访问私有的类成员,不过破坏了类的封装性。
7.25 答: 对于仅适用内置类型和字符串的类可以依赖于复制和分配(即可以使用浅拷贝) 而考虑到需要分配资源牵扯到指针时,这样是不可以的。
程序题:
题:7_13 和前面的变化不大,就是在建立对象的时候,直接初始化,向对象里面输入。改动如下:
Slaes_data total(cin);
if
(read(cin, total))
{
Slaes_data trans(cin);
while
(read(cin, trans))
{
题:7_15
#include
<iostream>
#include
<string>
using
namespace
std;
class
person
{
public
:
person() ;
//= default 新特性
person(string ad):adress(ad){}
person(
const
string &s, string ad):name(s),adress(ad){}
person(istream &in){read(in,*
this
);}
//直接从输入初始化,这种实现要记住。
string name;
string adress;
string print_name()
const
;
string print_adr()
const
;
};
string person::print_name()
const
{
return
this
->name;
}
string person::print_adr()
const
{
return
this
->adress;
}
istream &read(istream &in, person &per1)
{
in>>per1.name >> per1.adress;
return
in;
}
ostream &prin(ostream &ou,
const
person &per1)
{
ou<<per1.name << per1.adress;
return
ou;
}
题:7_21 (7_22类似)
#include
<iostream>
#include
<string>
using
namespace
std;
class
Slaes_data
{
private
:
string bookNo;
//图书编号
unsigned
unit_sold;
//售出数量
double
revecnue;
//销售总收入
public
:
friend
istream &read(istream &in, Slaes_data &item);
friend
ostream &prin(ostream &ou,
const
Slaes_data &item);
friend
Slaes_data add(
const
Slaes_data &item1,
const
Slaes_data &item2);
Slaes_data();
Slaes_data(
const
string &s ):bookNo(s){}
Slaes_data(
const
string &s,
unsigned
n,
double
p):
bookNo(s),unit_sold(n),revecnue(p){}
Slaes_data(istream &s){read (s,*
this
);}
string isbn()
const
{
return
(*
this
).bookNo;
}
Slaes_data &combine(
const
Slaes_data& );
int
avg_price()
const
;
};
Slaes_data::Slaes_data()
{
unit_sold = 0;
revecnue = 0;
}
Slaes_data& Slaes_data::combine(
const
Slaes_data &rhs)
{
this
->unit_sold += rhs.unit_sold;
this
->revecnue += rhs.revecnue;
return
*
this
;
}
int
Slaes_data::avg_price()
const
{
if
(
this
->unit_sold)
return
this
->revecnue/
this
->unit_sold;
else
return
0;
}
//类读入函数而该函数主要通过istream的对象然后集中输入到流里
//所以返回类型是istream,IO对象没有拷贝操作,无法传值,所以用引用,
istream &read(istream &in, Slaes_data &item)
{
double
price = 0;
in>>item.bookNo >> item.unit_sold >> price;
item.revecnue = item.unit_sold * price;
return
in;
}
//输出函数与 读入函数类似
ostream &prin(ostream &ou,
const
Slaes_data &item)
{
cout<<
"编号"
<<
'\t'
<<
"数量"
<<
'\t'
<<
"总价"
<<
'\t'
<<
"平均价"
<<endl;
ou<<item.isbn() <<
'\t'
<<item.unit_sold <<
'\t'
<<
item.revecnue<<
'\t'
<<item.avg_price();
return
ou;
}
Slaes_data add(
const
Slaes_data &item1,
const
Slaes_data &item2)
{
Slaes_data sum = item1;
//这里只拷贝数据成员
return
sum;
}
int
main(
int
argc,
char
*argv[])
{
cout<<
"请输入编号 "
<<
" 数量 "
<<
" 单价 "
<<endl;
Slaes_data total(cin);
if
(read(cin, total))
{
Slaes_data trans(cin);
while
(read(cin, trans))
{
if
(total.isbn() == trans.isbn())
{
}
else
{
prin(cout, total);
total = trans;
}
prin(cout, total)<<endl;
}
}
else
{
cout<<
"没有数据! "
<<endl;
return
-1;
}
return
0;
}
题:7_23,7_24
#include
<iostream>
#include
<string>
class
Screen
{
public
:
typedef
std::string::size_type pos;
Screen();
Screen(pos h, pos s,
char
c):height(h), width(s),contents(h*s,c){}
//第一个返回当前光标处的字符,第二个返回由行与列计算得来的。
char
get()
const
{
return
contents[cursor]; }
char
get(pos r, pos c)
const
{
return
contents[r * width + c]; }
private
:
// pos cursor = 0; C++11大改动,2010不支持
pos cursor;
pos height , width;
std::string contents;
}
int
main()
{
return
0;
}