C++篇:基础入门(二)

C++篇:基础入门(二)

在类外定义成员函数
在类的定义外面定义成员函数必须指明它们是类的成员:

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

形参表后面的 const 则反映了在类 Sales_item 中声明成员函数的形式。在任
何函数定义中,返回类型和形参表必须和函数声明(如果有的话)一致。对于成
员函数,函数声明必须与其定义一致。如果函数被声明为 const 成员函数,那
么函数定义时形参表后面也必须有 const。

现在可以完全理解第一行代码了:这行代码说明现在正在定义类 Sales_item 的
函数 avg_price,而且这是一个 const 成员函数,这个函数没有(显式的)形
参,返回 double 类型的值。

构造函数
构造函数是特殊的成员函数,与其他成员函数不同,构造函数和类同名,而且没有返回类型。而与其他成员函数相同的是,构造函数也有形参表(可能为空)和函数体。一个类可以有多个构造函数,每个构造函数必须有与其他构造函数不同数目或类型的形参。

构造函数的形参指定了创建类类型对象时使用的初始化式。通常,这些初始化式会用于初始化新创建对象的数据成员。构造函数通常应确保其每个数据成员都完成了初始化。

顺序容器
容器类共享公共的接口,这使标准库更容易学习,只要学会其中一种类型就能运用另一种类型。每种容器类型提供一组不同的时间和功能折衷方案。通常不需要修改代码,只需改变类型声明,用一种容器类型替代另一种容器类型,就可以优化程序的性能。

容器容纳特定类型对象的集合。我们已经使用过一种容器类型:标准库 vector类型,这是一种顺序容器(sequential container)。它将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素,这就是顺序容器。顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。

标准库定义了三种顺序容器类型:vector、list 和 deque(是双端队列“double-ended queue”的简写,发音为“deck”)。它们的差别在于访问元素的方式,以及添加或删除元素相关操作的运行代价。标准库还提供了三种容器适配器(adaptors)。实际上,适配器是根据原始的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。顺序容器适配器包括 stack、queue 和 priority_queue 类型

容器只定义了少量操作。大多数额外操作则由算法库提供,我们将在第十一章学习算法库。标准库为由容器类型定义的操作强加了公共的接口。这些容器类型的差别在于它们提供哪些操作,但是如果两个容器提供了相同的操作,则它们的接口(函数名字和参数个数)应该相同。

为了定义一个容器类型的对象,必须先包含相关的头文件,即下列头文件之一:

#include <vector>
#include <list>
#include <deque>

所有的容器都是类模板。要定义某种特殊的容器,必须在容器名后加一对尖括号,尖括号里面提供容器中存放的元素的类型:

vector<string>svec;// empty vector that can hold strings
list<int>ilist;// empty list that can hold ints
deque<Sales_item> items;// empty deque that holds Sales_items

所有容器类型都定义了默认构造函数,用于创建指定类型的空容器对象。默认构造函数不带参数。
为了使程序更清晰、简短,容器类型最常用的构造函数是默认构造函数。在大多数的程序中,使用默认构造函数能达到最佳运行时性能,并且使容器更容易使用。

当不使用默认构造函数,而是用其他构造函数初始化顺序容器时,必须指出该容器有多少个元素,并提供这些元素的初值。同时指定元素个数和初值的一个方法是将新创建的容器初始化为一个同类型的已存在容器的副本:

vector<int> ivec;
vector<int> ivec2(ivec);// ok: ivec is vector<int>
list<int> ilist(ivec);// error: ivec is not list<int>
vector<double> dvec(ivec); // error: ivec holds int not double

将一个容器复制给另一个容器时,类型必须匹配:容器类型和
元素类型都必须相同。

尽管不能直接将一种容器内的元素复制给另一种容器,但系统允许通过传递一对迭代器(第 3.4 节)间接实现该实现该功能。使用迭代器时,不要求容器类型相同。容器内的元素类型也可以不相同,只要它们相互兼容,能够将要复制的元素转换为所构建的新容器的元素类型,即可实现复制。迭代器标记了要复制的元素范围,这些元素用于初始化新容器的元素。迭代器标记出要复制的第一个元素和最后一个元素。采用这种初始化形式可复制不能直接复制的容器。更重要的是,可以实现复制其他容器的一个子序列:

// initialize slist with copy of each element of svec
list<string> slist(svec.begin(), svec.end());
// find midpoint in the vector
vector<string>::iterator mid = svec.begin() + svec.size()/2;
// initialize front with first half of svec: The elements up to but
not including *mid
deque<string> front(svec.begin(), mid);
// initialize back with second half of svec: The elements *mid
through end of svec
deque<string> back(mid, svec.end());

回顾一下指针,我们知道指针就是迭代器,因此允许通过使用内置数组中的一对指针初始化容器也就不奇怪了:

char *words[] = {"stately", "plump", "buck", "mulligan"};
// calculate how many elements in words
size_t words_size = sizeof(words)/sizeof(char *);
// use entire array to initialize words2
list<string> words2(words, words + words_size);

这里,使用 sizeof(5.8)计算数组的长度。将数组长度加到指向第一
个元素的指针上就可以得到指向超出数组末端的下一位置的指针。通过指向第一
个元素的指针 words 和指向数组中最后一个元素的下一位置的指针,实现了
words2 的初始化。其中第二个指针提供停止复制的条件,其所指向的位置上存
放的元素并没有复制。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值