C++ primer之第七章(类 2)

发现前面的笔记格式不是很好,后面会慢慢注意!


知识点:
    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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值