1.1 C++ 题目六
阅读下列说明和C++代码,填写程序中的空(1) ~(5),将解答写入答题纸的对应栏内。
【说明】
以下C++代码实现一个简单乐器系统,音乐类(Music)可以使用各类乐器(Instument)进行演奏和调音等操作。对部分乐器进行建模,其类图如图6-1所示,包括:乐器(Instrument)、打击乐器(Perussion)、 弦乐器(Stringed)、 管乐器( Wind)、木管乐器(Woodwind)、铜管乐器(Brass )。
cpp
#include<iostream>
#include<vector>
using namespace std;
enum Note{ /*枚举各种高调*/
MIDDLE_C,C_SHARP,B_FLAT //其它略
};
class Instrument { /*抽象基类,乐器*/
public:
( 1 ) ; //纯虚函数play
virtual void adjust()=0; //adjust函数接口
};
class Wind:( 2 ) {
public:
void play(Note n){cout<< "Wind.play() "<<n<<endl; }
void adjust(){cout<< "Wind.adjust() "<<endl; }
};
/*类Percussion 和Stringed实现代码略*/
class Brass: ( 3 ) {
public:
void play(Note n){cout<< "Brass.play() "<<n<<endl: }
void adjust(){cout<< "Brass.adjust() "<<endl; }
};
class Woodwind:public Wind {
public:
void play(Note n){cout<< "Woodwind.play() "<<n<<endl: }
};
class Music{
public:
void tune(Instrument*i){ i->play(MIDDLE_C); }
void adjust(Instrument*i){ i->adjust(); }
void tuneAll( ( 4 ) v ) { /*为每个乐器定调*/
vector<Instrument*>::iterator it;
for(it=v.begin();it!=v.end();it++) {
this->adjust(*it);
this->tune(*it);
}
}
};
int main()
{
( 5 ) music=new Music();
vector<Instrument*>orchestra;
orchestra.push_back(new Wind());
music->tuneAll(orchestra);
}
1.1.1 填空(1)
由于空(1)
已经注释为 存虚函数,所以我们知道,这个函数肯定会在它的子类中实现,所以只需要到子类中找到该该函数的参数类型及返回值类型即可。
cpp
class Instrument{ /*抽象基类,乐器*/
public:
( 1 ) ; //纯虚函数play
virtual void adjust()=0; //adjust函数接口
};
class Wind: ( 2 ) {
public:
void play(Note n){cout<< "Wind.play() "<<n<<endl; }
void adjust(){cout<< "Wind.adjust() "<<endl; }
};
所以空(1)
填 virtual void plya(Note) { }=0;
,因为类Wind
基层基类Instrument
。
1.1.2 填空(2)
由于类Wind
中实现了 类Instrucment
中定义的存虚函数,所以我们可以知道,Wind
是Instrucment
的子类,所以空(2)
应该填继承方式:public Instrument
。
1.1.3 填空(3)
有题目总中给出的图,我们也可以知道 Brass
是Wind
子类,所以空(3)
也应该填写继承方式public Wind
。
cpp
class Wind: ( 2 ) {
public:
void play(Note n){cout<< "Wind.play() "<<n<<endl; }
void adjust(){cout<< "Wind.adjust() "<<endl; }
};
/*类Percussion 和Stringed实现代码略*/
class Brass: ( 3 ) {
public:
void play(Note n){cout<< "Brass.play() "<<n<<endl: }
void adjust(){cout<< "Brass.adjust() "<<endl; }
};
1.1.4 填空(4)
代码中可以看到Music
是一个基类,tuneAll((4)v)
是一个成员函数,无法从上面代码得到有用信息,所以只能从函数内容获取有用信息,函数内部用到了类Instrument
。
cpp
class Music {
public:
void tune(Instrument*i){ i->play(MIDDLE_C); }
void adjust(Instrument*i){ i->adjust(); }
void tuneAll( ( 4 ) v ) { /*为每个乐器定调*/
vector<Instrument*>::iterator it;
for(it=v.begin();it!=v.end();it++) {
this->adjust(*it);
this->tune(*it);
}
}
};
vector<Instrument*>::iterator it
定义了一个迭代器 it
,这个迭代器用于遍历一个存储了Instrument
指针 的 vector容器。下面是对这个表达式的详细解释:
vector<Instrument*>
:这是一个存储了 Instrument 类型指针的 vector容器。Instrument*
是指向 Instrument类型对象的指针。iterator
:这是vector
容器的一个内置类型,它是一个迭代器类型,用于遍历vector
容器中的元素。it
:这是迭代器的实例的名称。
迭代器提供了一个统一的接口,用于访问容器中的元素,和这些元素的读取、修改等操作。在很多方面,迭代器的行为类似于指针。
由上面内容可以知道空(4)
应该是一个向量指针,向量的类型为Instrument
, 所以空(4)
应该填 vector<Instrument*>
1.1.4.1 C++ vector
学习向量之前先了解下 什么是STL?
-
1、STL (Standard Template Library),即标准模板库,是一个高效的C++程序库 ,包含了诸多常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。
-
2、从逻辑层次来看,在STL中体现了泛型化程序设计的思想(generic programming)。在这种思想里,大部分基本算法被抽象,被泛化,独立于与之对应的数据结构,用于以相同或相近的方式处理各种不同情形。
-
3、从实现层次看,整个STL是以一种类型参数化(type parameterized)的方式实现的,基于模板(template)。
STL有六大组件 ,但主要包含容器 、迭代器和算法三个部分。
- 容器 (Containers):用来管理某类对象的集合。每一种容器都有其优点和缺点,所以为了应付程序中的不同需求,STL 准备了七种基本容器类型。
- 迭代器 (Iterators):用来在一个对象集合的元素上进行遍历动作 。这个对象集合或许是个容器,或许是容器的一部分。每一种容器都提供了自己的迭代器,而这些迭代器了解该种容器的内部结构。
- 算法(Algorithms):用来处理对象集合中的元素,比如 Sort,Search,Copy,Erase 那些元素。通过迭代器的协助,我们只需撰写一次算法,就可以将它应用于任意容器之上,这是因为所有容器的迭代器都提供一致的接口。
STL
的基本观念就是将数据和操作分离。数据由容器进行管理,操作则由算法进行,而迭代器在两者之间充当粘合剂,使任何算法都可以和任何容器交互运作。这一篇博客暂时只介绍容器,下一篇介绍迭代器。
容器用来管理某类对象。为了应付程序中的不同需求,STL 准备了两类共七种基本容器类型:
- 序列式 容器(Sequence containers),此为可序群集,其中每个元素均有固定位置---取决于插入时机和地点,和元素值无关。如果你以追加方式对一个群集插入六个元素,它们的排列次序将和插入次序一致。STL提供了三个序列式容器 :
- 向量(vector)、
- 双端队列(deque)、
- 列表(list),
- 此外你也可以把 string 和 array 当做一种序列式容器。
- 关联式容器(Associative containers),此为已序群集,元素位置取决于特定的排序准则以及元素值,和插入次序无关。如果你将六个元素置入这样的群集中,它们的位置取决于元素值,和插入次序无关。STL提供了四个关联式容器:集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)。
1.1.4.2 vector(向量)
它是一种序列式容器,事实上和数组差不多 ,但它比数组更优越。一般来说数组不能动态拓展,因此在程序运行的时候不是浪费内存,就是造成越界。而 vector 正好弥补了这个缺陷,当内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。
C++的初始化方法很多,各种初始化方法有一些不同。
-
(1):
vector<int> ilist1
;默认初始化,vector为空, size为0,表明容器中没有元素,而且 capacity 也返回 0,意味着还没有分配内存空间。这种初始化方式适用于元素个数未知,需要在程序中动态添加的情况。
-
(2):
vector<int> ilist2(ilist)
;
vector<int> ilist2 = ilist
;两种方式等价 ,ilist2 初始化为ilist 的拷贝,ilist必须与ilist2 类型相同,也就是同为int的vector类型,ilist2将具有和ilist相同的容量和元素
-
(3):
vector<int> ilist = {1,2,3.0,4,5,6,7}
;
vector<int> ilist {1,2,3.0,4,5,6,7}
;ilist 初始化为列表中元素的拷贝,列表中元素必须与ilist的元素类型相容,本例中必须是与整数类型相容的类型,整形会直接拷贝,其他类型会进行类型转换。
-
4):
vector<int> ilist3(ilist.begin()+2,ilist.end()-1)
;ilist3初始化为两个迭代器指定范围中元素的拷贝,范围中的元素类型必须与
ilist3
的元素类型相容,在本例中ilist3
被初始化为{3,4,5,6}
。 -
5):
vector<int> ilist4(7)
;默认值初始化,ilist4中将包含7个元素,每个元素进行缺省的值初始化,对于
int
,也就是被赋值为0
,因此ilist4
被初始化为包含7个0。 -
(6):
vector<int> ilist5(7,3)
;指定值初始化,ilist5被初始化为包含7个值为3的int
1.1.5 填空(5)
从下面代码中可以看到,在main
函数中创建了一个类型为Instrument*
的向量orchestra
, 然后通过push_back(new Wind())
它向向量orchestra
中插入元素。再调用成员函数tuneAll
,由于这个函数只在Music
类中实现的,所以空(5)
应该填Music *
cpp
int main()
{
( 5 ) music=new Music();
vector<Instrument*>orchestra;
orchestra.push_back(new Wind());
music->tuneAll(orchestra);
}
pop_back()
&push_back(elem)
实例在容器最后移除和插入数据,如下:
c
#include <string.h>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<int>obj;//创建一个向量存储容器 int
for(int i=0;i<10;i++) // push_back(elem)在数组最后添加数据
{
obj.push_back(i);
cout<<obj[i]<<",";
}
for(int i=0;i<5;i++)//去掉数组最后一个数据
{
obj.pop_back();
}
cout<<"\n"<<endl;
for(int i=0;i<obj.size();i++)//size()容器中实际数据个数
{
cout<<obj[i]<<",";
}
return 0;
}
输出结果为:
cpp
0,1,2,3,4,5,6,7,8,9,
0,1,2,3,4,