一、选择题
下面叙述错误的是(A)
A.基类的protected成员在派生类中仍然是protected
B.基类的protected成员在public派生类中仍然是protected的
C.基类的protected成员在private派生类中是private的
D.基类的protected成员不能被派生类的对象访问
解析:
权限运算规则:
public > protecetd > private
(继承方式 与 基类中权限 )取交集 = 派生类中权限
2、下列对派生类的描述中,(D)是错误的。
A.一个派生类可以作为另一个派生类的基类
B.派生类至少有一个基类
C.派生类的成员除了它自己的成员外,还包含了它的基类成员
D.派生类中继承的基类成员的访问权限到派生类保持不变
3、派生类的对象对它的哪一类基类成员是可以访问的?(A)
A.公有继承的基类的公有成员 B. 公有继承的基类的保护成员
C. 公有继承的基类的私有成员 D. 保护继承的基类的公有成员
4、关于多继承二义性的描述,(D)是错误的。
A.派生类的多个基类中存在同名成员时,派生类对这个成员访问可能出现二义性
B.一个派生类是从具有共同的间接基类的两个基类派生来的,派生类对该公共基类的访问可能出现二义性
C.解决二义性最常用的方法是作用域运算符对成员进行限定
D.派生类和它的基类中出现同名函数时,将可能出现二义性
派生类和它的基类中出现同名函数,如果与基类中虚函数同名,则是覆盖。
如果和非虚函数同名,则是隐藏。
5、设有基类定义:
class Base
{
private:
int a;
protected:
int b;
public:
int c;
};
派生类采用何种继承方式可以使成员变量b成为自己的私有成员( A )
A. 私有继承 B.保护继承C. 公有继承 D.私有、保护、公有均可
二、填空题
1、在继承机制下,当对象消亡时,编译系统先执行[ 派生类 ] 的析构函数,然后才执行 [ 派生类中成员对象 ] 的析构函数,最后执行 [基类] 的析构函数。
三、改错题以及写结果题。
1、指出并改正下面程序中的错误。
#include<iostream>
using std::cout;
using std::endl;
class Point
{
public:
Point(int a=0, int b=0)
{
x = a;
y = b;
}
void move(int xoffset,int yoffset)
{
x += xoffset;
y += yoffset;
}
int getx()
{
return x;
}
int gety()
{
return y;
}
private:
int x,y;
};
class Rectangle
:protected Point
{
public:
Rectangle(int x, int y, int l, int w)
: Point(x,y)
{
length = l;
width = w;
}
int getLength()
{
return length;
}
int getWidth()
{
return width;
}
private:
int length;
int width;
};
int main()
{
Rectangle r(0, 0, 8,4);
r.move(23,56);
cout << r.getx()
<< "," << r.gety()
<< "," << r.getlength()
<< "," << r.getwidth() << endl;
return 0;
}
答:三处错误:
1.protected---->public
2.r.getlength() -->r.getLength();
3.r.getwidth() --->r.getWidth();
2、指出并改正下面程序中的错误。
#include<iostream>
using std::cout;
using std::endl;
class A
{
public:
int x;
A(int a = 0)
{
x = a;
}
void display()
{
cout<< "A.x = " << x << endl;
}
};
class B
{
public:
int x;
B(int a = 0)
{
x=a;
}
void display()
{
cout<<"B.x = " << x << endl;
}
};
class C
:public A
,public B
{
public:
C(int a, int b, int c)
: A(a)
, B(b)
{
y=c;
}
int gety()
{
return y;
}
private:
int y;
};
int main()
{
C myc(1,2,3);
myc.x = 10;
myc.display();
return 0;
}
答:
访问基类中的成员变量和函数需要加作用域,避免二义性:
myc.x = 10;----->myc.B::x=10或者myc.A::x=10
myc.display();------->myc.B::display()或者myc.A::display();
3、看程序写结果
#include<iostream>
using std::cout;
using std::endl;
class Base
{
public:
Base(int n)
{
cout <<"Constucting base class" << endl;
_ix = n;
}
~Base()
{
cout <<"Destructing base class" << endl;
}
void showX()
{
cout << _ix << ",";
}
int getX()
{
return _ix;
}
private:
int _ix;
};
class Derived
:public Base
{
public:
Derived(int n, int m, int p)
: Base(m)
, _base(p)
{
cout << "Constructing derived class" <<endl;
j = n;
}
~Derived()
{
cout <<"Destructing derived class"<<endl;
}
void show()
{
Base::showX();
cout << j << "," << _base.getX() << endl;
}
private:
int j;
Base _base;
};
int main()
{
Derived obj(8,13,24);
obj.show();
return 0;
}
结果:
Constucting base class
Constucting base class
Constructing derived class
13,8,24
Destructing derived class
Destructing base class
Destructing base class
四、简答题
1、三种继承方式对于基类成员的访问权限是怎样的?
1. 派生类中的访问权限计算公式:
( 继承形式 与 基类成员权限 ) 取交集 = 派生类中访问权限2.基类成员中的私有成员继承后都不可直接访问
3.派生类中对象访问权限: 派生类以共有方式继承基类,实例化出来的的对象只可访问基类的公有成员
2、继承中有哪些内容是不能进行继承的?
1.构造函数
2.析构函数
3.用户重载的operator new/delete运算符
4.用户重载的=运算符
5.友元关系
3、多基派生会产生的问题有哪些?怎样解决?
(1)成员名冲突二义性
问题原因:所继承的多个基类中存在同名成员,从而吸收到了不同基类的同名成员
解决方法:通过基类的命名域访问从相应基类中继承而来的成员菱形继承二义性
问题原因:所继承的基类中有多个基类又有着共同基类,从而在该派生类中会吸收来自不同路径的共同基类成员的多重拷贝
解决方法:(1)通过基类的命名域访问从相应基类中继承而来的成员。(2)使用虚继承
五、编程题。
1、编写一个圆类Circle,该类拥有:
① 1个成员变量,存放圆的半径; ② 两个构造方法 Circle( ) // 将半径设为0 Circle(double r ) //创建Circle对象时将半径初始化为r ③ 三个成员方法 double getArea( ) //获取圆的面积 double getPerimeter( ) //获取圆的周长 void show( ) //将圆的半径、周长、面积输出到屏幕
2、编写一个圆柱体类Cylinder,它继承于上面的Circle类,还拥有: ① 1个成员变量,圆柱体的高;② 构造方法 Cylinder (double r, double h) //创建Circle对象时将半径初始化为r ③ 成员方法double getVolume( ) //获取圆柱体的体积 void showVolume( ) //将圆柱体的体积输出到屏幕 编写应用程序,创建类的对象,分别设置圆的半径、圆柱体的高,计算并分别显示圆半径、圆面积、圆周长,圆柱体的体积。
#include <iostream>
using namespace std;
class Circle
{
public:
Circle()
:_r(0)
{
cout<<"Circle的无参 构造函数"<<endl;
}
Circle(double r)
:_r(r)
{
cout<<"Circle的有参构造函数"<<endl;
}
double getArea()//获取圆的面积
{
return 3.14*_r*_r;
}
double getPerimeter()//获取圆的周长
{
return 2.0*3.14*_r;
}
void show()
{
cout<<"半径:"<<_r<<endl
<<"面积:"<<getArea()<<endl
<<"周长:"<<getPerimeter()<<endl;
}
private:
double _r;
};
class Cylinder:public Circle
{
public:
Cylinder(double r, double h)
:Circle(r) //调用基类构造函数来初始化半径
,_h(h)
{
cout<<"Cylinder有参构造函数"<<endl;
}
double getVolume()//获取圆柱体体积
{
return getArea()*_h;
}
void showVolumn()
{
cout<<"Cylinder的体积:"<<getVolume()<<endl;
}
private:
double _h;
};
void test01()
{
Circle s1(10);
s1.show();
Cylinder c(10,10);
c.showVolumn();
}
int main()
{
test01();
return 0;
}
运行结果
Circle的有参构造函数
半径:10
面积:314
周长:62.8
Circle的有参构造函数
Cylinder有参构造函数
Cylinder的体积:3140
3、构建一个类Person,包含字符串成员name(姓名),整型数据成员age(年龄),成员函数 display()用来输出name和age。构造函数包含两个参数,用来对name和age初始化。构建一个类Employee由Person派生,包含department(部门),实型数据成员salary(工资),成员函数display()用来输出职工姓名、年龄、部门、工资,其他成员根据需要自己设定。主函数中定义3个Employee类对象,内容自己设定,将其姓名、年龄、部门、工资输出,并计算他们的平均工资。
#include <iostream>
#include <string.h>
using namespace std;
class Person
{
public:
Person(string name, int age)
:_name(name)
,_age(age)
{
cout<<"Person()"<<endl;
}
void display()
{
cout<<"name:"<<_name<<endl
<<"age:"<<_age<<endl;
}
private:
string _name;
int _age;
};
class Employee:public Person
{
public:
Employee(string name,int age, string department, float salary)
:Person(name,age),//名字和年龄要调用基类的构造函数来初始化
_department(department),
_salary(salary)
{
CounSalary+=salary;
Count_employee +=1;
cout<<"Employee()"<<endl;
}
void display()
{
cout<<Count_employee<<"号员工信息如下:"<<endl;
this->Person::display();//名字和年龄的显式需要用作用域形式来调用
cout <<"department:"<<_department<<endl
<<"Salary:"<<_salary<<endl;
cout<<endl;
}
static void show_Ave_Salary()
{
cout<<"总员工:"<<Count_employee<<endl
<<"平均工资:"<<CounSalary/Count_employee<<endl;
}
private:
string _department;//部门
float _salary;//工资
static float CounSalary;//员工总薪资
static int Count_employee;//总员工人数
};
float Employee::CounSalary = 0;
int Employee::Count_employee = 0;
void test01()
{
Employee e1("Tom",12,"Wipasx",3000);
e1.display();
Employee e2("Gogo",14,"Testing",8999);
e2.display();
Employee e3("Peter",21,"FA", 7878);
e3.display();
cout<<"员工创建完毕"<<endl;
Employee::show_Ave_Salary();
}
int main()
{
test01();
return 0;
}
运行结果
Person()
Employee()
1号员工信息如下:
name:Tom
age:12
department:Wipasx
Salary:3000Person()
Employee()
2号员工信息如下:
name:Gogo
age:14
department:Testing
Salary:8999Person()
Employee()
3号员工信息如下:
name:Peter
age:21
department:FA
Salary:7878员工创建完毕
总员工:3
平均工资:6625.67
4、词频统计的作业再用map容器去实现一次,体验一下使用vector/map时程序执行的速度++dict[word];
Bible.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include<string>
#include <vector>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <iomanip>
#include <map>
#include <time.h>
class Dictionary
{
public:
void read(const string &filename);//1.读取圣经,进行字符统计,把结果并且存入_dict vector
//void dict_Sort();//排序
void foreach_map();//遍历map
void store(const string &filename);//2.从map中把结果写入新文件
private:
map <string, int>_dict;
string int2String(int number);//int类型转为字符串流,ostringstream
void trim(string &s);//string字符串去掉首尾空格
bool judgefullword(string &word);//判断单词是否正确
};
bible.cc
#include "Bible.h"
void Dictionary::read(const string &filename)//读取数据并且进行处理
{
ifstream ifs(filename);//1.ifstream 从文件中读取数据
if (!ifs.good())//文件不存在就退出
{
cerr << "ifstream is not good" << endl;
return;
}
string word;
while (ifs >> word)//2.默认以空格为分隔符,每次读一个单词
{
//istringstream ss(word); //把word变成string流
//string key; //用来接收string
//ss >> key; //key接收读出来的字符串
//把key中的字符,大写变成小写
for (int i = 0; i < word.size(); i++)//3.把单词的大写转成小写,非字母类型转为空格
{
if (word[i] >= 'A' && word[i] <= 'Z')
{
word[i] += 32;
}
if (word[i] >= 'a' &&word[i] <= 'z')
{
continue;
}
word[i] = ' '; //标点符号变成空格
}
trim(word); //4.去掉word的首尾空格,如果word全是空字符, 会把word置空,word.empty()会为真
bool flag_no_error = judgefullword(word);//5.去掉首尾空格后,单词中间还有其他不合法字符,就跳过这个单词
if (!word.empty()&&flag_no_error==true)//6.单词不为空,并且为合法单词
{
if (_dict.empty())//7.如果_dict为空,直接把单词插入map容器
{
_dict.insert(make_pair(word,1));//map容器插入
}
else
{
map<string, int>::iterator ret = _dict.find(word);
//8.如果_dict不空,先判断_dict中是否有该单词,有的话,对应词频加1
if (ret != _dict.end()) //ret是个map迭代器
{
ret->second++;//ret是word在_dict中的位置,词频加1
}
else
{
_dict.insert(make_pair(word,1));
}
}
}
}
}
//string字符串去掉首尾空格
void Dictionary::trim(string &s)
{
if (!s.empty())
{
s.erase(0, s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + 1);
}
}
//判断读出来的单词是否正确
bool Dictionary::judgefullword(string &word)
{
for (int i = 0; i < word.size(); i++)
{
if (word[i]<'a' || word[i]>'z')
return false;
}
return true;
}
void Dictionary::foreach_map()//遍历map
{
int i = 1;
for(map<string, int>::iterator it=_dict.begin(); it!=_dict.end();it++)
{
//cout<<it->first<<"\t"<<it->second<<endl;
cout<< int2String(i) << " " //单词序号,把int转成string
<<setiosflags(ios::left)<<setw(32)<< it->first<<"\t"//单词对齐
<< it->second<< endl;//词频
i++;
}
}
//把int转成string
string Dictionary::int2String(int number)
{
ostringstream oss;
oss << number; //把number写入oss流
return oss.str();//返回oss字符串
}
//把统计数据输出到文件
void Dictionary::store(const string &filename)
{
ofstream ofs(filename);//ofstream,把结果数据输出到文件
if (!ofs.good())
{
cerr << "ofstream is not good " << endl;
return;
}
#if 0
for (int i = 0; i < _dict.size(); i++)
{
ofs <<int2String(i+1) <<" "<<_dict[i]._word << " " << _dict[i]._frequency << endl;
}
#endif
ostringstream my_ss;
int i = 1;
for (map<string,int>::iterator it=_dict.begin();it!=_dict.end();it++)
{
//1.把数据先对齐写入字符串流
my_ss << int2String(i) << " " //单词序号,把int转成string
<<setiosflags(ios::left)<<setw(32)<<it->first<<"\t"//单词对齐
<< it->second << endl;//词频
i++;
}
//cout << my_ss.str() << endl;
//2.再把数据写入到文件
ofs << my_ss.str() << endl;
ofs.close();
}
main.cc
#include "Bible.h"
void test01()
{
Dictionary s1;
clock_t start, end;
start = clock();//开始时间
s1.read("The_Holy_Bible.txt"); //1.读取圣经数据,统计单词词频,存入map
//s1.dict_Sort(); //2.对map中的单词进行排序
s1.foreach_map();//3.遍历词典map,把结果输出到控制台
s1.store("my_dict.txt");//4.把结果存入文件
end = clock();//结束
cout<<"Time:"<<double(end-start)/CLOCKS_PER_SEC <<"s"<<endl;
}
int main()
{
test01();
return EXIT_SUCCESS;
}
运行结果,使用map容器来完成,比vector容器速度快很多:
Time:0.851361s
(Day6仅使用vecotr)运行结果:
Time:12.584s