c++11Primer(第七章)

类的简介

最开始的时候我们用struct定义了一个数据结构

struct Sales_data{
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    };

c++11标准规定可以为数据成员提供一个类内初始值。创建对象时,类内初始值用于初始化数据成员。没有初始值的成员将被默认初始化。(默认初始化:对于内置类型,如果定义于任何函数之外则被初始化为0,如果定义在函数体内部,则内置类型变量不被初始化。类的对象没有显示初始化,其值由类确定。)类内的初始值可以放在花括号里,或者等号右边,但是不能使用圆括号。

使用Sales_data类

可以像使用内置类型一样定义这种类型的变量

Sales_data data1,data2;

我们的目的是让Sales_data类支持的操作:
一个isbn成员函数
一个combine成员函数,用于将一个Sales_data对象与另一个Sales_data相加
一个add函数,执行两个Sales_data对象的加法
一个read函数,将数据从istream读入到Sales_data对象中
一个print函数,用于输出Sales_data对象的值到ostream

std::string isbn() const {return bookNo;}

虽然这个函数很简单,但是还是有些知识点的。首先这个函数定义在类的内部,也就是说这个函数默认是inline的。inline函数没有函数调用的帧栈操作,因为在编译阶段inline函数会被替换为他的函数体。此函数声明之后的const标明这个函数不会改变调用他的对象。

Sales_data& combine(const Sales_data&);

用引用得到方式传值可以减少传入值的拷贝操作,利用pass-by-const-reference来提高性能。如果我们返回的值是一个引用,那么就可以不使用c++的return-by-value的这种机制,而变成return-by-reference。

std::ostream& print(std::ostream&,const Sales_data&);

IO对象是不能够被copy的,所以使用pass-by-reference和return-by-reference来实现参数的传递和返回值的传递。

当我们在调用成员函数的时候:

total.isbn();

我们实际上是在替某个对象调用isbn()。如果isbn()指向Sales_data的某个成员,则它隐式的指向调用该函数的对象的成员。成员函数通过一个隐士的this指针来访问调用它的那个对象。我们的this指针是一个常指针,也就是说他保存的地址是不会改变的。如果我们要让this指针所指向的对象也是const的,那么我们就要在成员函数的末尾加上const关键字。在这里,this的类型是 Sales_data * const,也就是说,我们可以通过解引用this来更获得这个对象,进而对其进行更改。所以this不能绑定在const对象上,因为const对象返回的是 Sales_data const *。const对象,以及const对象的引用或指针都只能调用常量成员函数。

类的作用域

只需记住一句话:编译器分两步处理类:首先编译成员的声明,然后才轮到成员函数体。因此,成员函数体可以随意使用类中的其他成员而无需在意这些成员出现的次序。

在类的外部定义成员函数

如果成员被声明成常量成员函数,那么它的定义也必须在参数列表后明确指定const属性。同时,类外部定义的成员的名字必须包含它所属的类名。

double Sales_data::avg_price() const {
    if(units_sold)
        return revenue/units_sold;
    else
        return 0;
}

函数名Sales_data::avg_price使用作用于操作符来说明如下的事实:我们定义了一个名为avg_price的函数,并且该函数被声明在类Sales_data的作用域内。一旦编译器看到这个函数名,就能理解剩余的代码是位于类的作用于内的。

定义一个返回this对象的函数

return *this;

return语句解引用this指针以获得执行该函数的对象。

构造函数

不同于其他成员函数,构造函数不能被声明成const的。当我们创建类的一个const对象时,指导构造函数完成初始化过程,对象才能整整取得其“常量”属性。因此,构造函数在const对象的构造过程中可以向其写值。也就是说不管是const对象还是非const对象的创建过程,用到的构造函数是同一个。所以构造函数加不加const没有任何影响,所以标准规定不能加const。

合成的默认构造函数

只有没有定义任何一个构造函数时,编译器才会为我们生成默认的构造函数。默认构造函数采取的初始化方式为:如果存在类内的初始值,则用它来初始化成员,否则,默认初始化该成员。

某些类并不能依赖于默认的构造函数。比如数据成员有内置类型或者复合类型,合成的默认构造函数将会对这些数据成员进行默认初始化,而默认初始化得到的结果,可能就是未定义的值。另一种情况是,类中有没有默认构造函数的成员,这样在使用默认构造函数时,将会因为该成员没有默认构造函数而报错。

=default的含义

我们希望这个函数的作用完全等同于之前使用的合成默认构造函数。

构造函数初始值列表

初始化顺序和变量声明的顺序一致。

拷贝、赋值和析构

对象在集中情况下会被拷贝,如我们初始化变量以及以值的方式传递或返回一个对象等。当我们使用了赋值运算符时会发生对象的赋值操作。当对象不再存在时执行销毁的操作,比如一个局部对象会在创建他的块结束时被销毁。

友元

类可以允许其他类或者函数访问它的非公有成员,方法是令其他类或者函数成为它的友元。
友元的声明仅仅指定了访问的权限,而非一个通常意义上的函数声明。如果我们希望类的用户能够调用某个友元函数,那么我们就必须在友元声明之外再专门对函数进行一次声明。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值