一、填空題
(1)如類果類A繼承了B,那麼類A被稱爲 基 類,而類B被稱爲 派生 類。
(2)C++的兩種繼承爲: 單繼承 和 多繼承 。
(3)在默認情況下的繼承方式爲 私有繼承方式 。
(4)從基類中公有派生一個類時,基類的公有成員就成爲派生類的 公有 成員,而這個基類的保護成員就成爲派生類的 保護成員。
(5)C++提供了 多繼承 機制,允許一個派生類可以繼承多個基類,甚至這些基類是互不相關的。
(6)類X中的名字N 支配類Y中同名的名字N,是指類X以類Y爲它的一個基類,這稱爲 支配規則 。
(7)引進虛基類的目的是 解決二義性 。
(8)在一個繼承結構中,解決二義性的方法有 使用作用域運算符 和 引進虛基類 。
二、選擇題(至少選一個,可以多選)
(1)C++語言建立類族是通過( B )。
A.類的嵌套 B.類的繼承 C.虛函數 D.抽象類
(2) 繼承是( CD )的方法。
A.將特殊的類變成通用的類
B.將通用的參數傳送給特殊的類的對象
C.將通用的類變成特殊的類
D.將已有的類添加新的特性,但不重寫它們
(3)繼承的優點是( ABC )。
A.擴大類的使用範圍,更便於使用類庫
B.避免重寫程序代碼,提供有用的概念框架
C.把類轉化成有條理的層次結構
D.通過繼承的自然選擇和重寫使類進一步拓展
(4)下面敘述不正確的是( C )。
A.基類的保護成員在保護派生類中仍然是保護的
B.基類的保護成員在公有派生類中仍然是保護的
C.基類的保護成員在私有派生類中仍然是保護的
D.對基類的保護成員的訪問必須是無二義性的
(5)派生類的對象對它的基類成員中( A )是可以訪問的。
A.公有繼承的公有成員
B.公有繼承的私有成員
C.公有繼承的保護成員
D.私有繼承的公有成員
(6)( C )是可以訪問類對象的私有數據成員的。
A.該類的對象 B.該類友元類派生的成員函數 C.類中的友元函數 D.公有派生類的成員函數
(7)多繼承是( B )。
A.多個單繼承的疊加
B.派生類有多個直接基類
C.多個派生類有唯一的基類
D.每個派生類最多隻有一個直接基類,但它可以有多個間接基類
(8)關於多繼承二義性的描述,( D )是錯誤的。
A.派生類的多個基類中存在同名成員時,派生類對這個成員訪向可能出現二義性
B.由於二義性原因,一個類不能從同一個類中一次以上直接繼承
C.使用作用域運算符對成員進行限制可以解決二義性
D.派生類和它的基類中出現同名函數時,派生類對這個成員函數的訪問可能出現二義性
(9) 作用域運算符通常用來( AD )。
A.指定特定的類
B.指明從哪一個基類中導出來的
C.在某些成員函數中限定靜態變量的可視範圍
D.解決二義性
(10)多繼承派生類析構函數釋放對象時,( A )被最先調用。
A.派生類自己的析構函數
B.基類的析構函數
C.根基類的析構函數
D.派生類中子對象類的析構函數
三、判斷題
(1)增加一個基類的派生類,需要對基類進行根本改變。(錯)
(2)如果沒有爲派生類指定構造函數,則派生類的對象會調用基類的構造函數。(對)
(3)對一個類來說,可能的訪問權限爲: private.public.protected 和不可訪問。(錯)
(4)無論哪種派生方式,基類中的私有成員在派生類中都是不可訪問的。(對)
(5)在派生過程中,派生類繼承包括構造函數和析構函數在內的所有基類成員。(錯)
(6) 在單繼承中,派生類對象對基類成員函數的訪問也可能出現二義性。(錯)
四、筒答題
(1)在面向對象技術中,類與類之間的關係如何表示?
答:在面向對象技術中,類是數據和操作的集合,它們之間主要有3中關係:Has-A、Uses-A和Is-A。
Has-A表示類的包含關係,用以描述一個類由多個“部件類”構成。在面向對象技術中,實現Has-A關係用類成員表示,即第3章中已學的子對象。
Uses-A表示一個類部分地使用另一個類。在面向對象技術中,這種關係通過類之間成員函數的相互聯繫或對象參數傳遞實現。另外,通過定義友元也能實現這種關係。
Is-A表示一種分類方式,描述類的抽象和層次關係。
(2)簡述賦值兼容規則。
答:所謂賦值兼容規則是指在公有繼承情況下,一個派生類的對象可以作爲基類的對象來使用。具體來說,就是下面3種情況:
①派生類的對象可以賦給基類的對象。
②派生類的對象可以初始化基類的引用。
③派生類的對象的地址可以賦給指向基類的指針。
(3)簡述在 3 種繼承方式下基類成員的訪問權限。
答:當類的繼承方式爲公有繼承時,在派生類中,基類的公有成員和保護成員被繼承後分別作爲派生類的公有成員和保護成員,這樣使得派生類的成員函數可以直接訪問它們,而派生類的成員函數無法直接訪問基類的私有成員。 在類外部,派生類的對象可以訪問繼承下來的基類公有成員。
當類的繼承方式爲私有繼承時,在派生類中,基類的公有成員和保護成員作爲派生類的私有成員,派生類的成員函數可以直接訪問它們,而派生類的成員函數無法直接訪問基類的私有成員。在類外部,派生類的對象無法訪問基類的所有成員。
當類的繼承方式爲保護繼承時,在派生類中,基類的公有成員和保護成員作爲派生類的保護成員,派生類的成員函數可以直接訪問它們,而派生類的成員函數無法直接訪問基類的私有成員。在類外部,派生類的對象無法基類的所有成員。
(4)簡述在繼承方式下創建派生類對象時,構造函數調用順序,以及刪除派生類對象時派生類析構函數的調用順序。
答:創建派生類對象時構造函數調用順序:首先調用基類構造函數,子對象所在類構造函數次之,最後執行派生類構造函數。
刪除派生類對象時派生類析構函數的調用順序:先調用派生類的析構函數;再調用派生類中子對象類的析構函數;再調用普通基類的析構函數;最後調用虛基類的析構函數。
(5) 簡述派生類構造函數的規則。
答:第1種情況:若派生類有構造函數而基類沒有,當創建派生類的對象時,派生類相應的構造函數會被自動調用。
第2種情況:若派生類沒有構造函數而基類有,則基類必須擁有默認的構造函數。只有這樣,當創建派生類的對象時,才能自動調用基類的默認構造函數。
第3種情況:若派生類有構造函數,且基類有默認構造函數,則創建派生類的對象時,基類的默認構造函數會自動調用,除非當前被調用的派生類構造函數在其初始化列表中顯示調用了基類的有參構造函數。
第4種情況:若派生類和基類都有構造函數,但基類沒有默認構造函數,則派生類的每一個構造函數必須在其初始化列表中顯示調用基類的某個構造函數。只有這樣,當創建派生類的對象時,基類的構造函數才能獲得執行機會。
五、程序分析題(寫出程序的輸出結果)
#include<iostream>
using namespace std;
class A
{
public:
A(int i,int j){a=i;b=j;}
void move(int x,int y){a+=x;b+=y;}
void disp()
{
cout<<"("<<a<<","<<b<<")"<<endl;
}
private:
int a,b;
};
class B:public A
{
public:
B(int i,int j,int k,int l):A(i,j),x(k),y(l){}
void disp()
{
cout<<x<<","<<y<<endl;
}
void fun1(){ move(13,15);}
void fun2(){A::disp();}
private:
int x,y;
};
int main()
{
A aa(11,12);
aa.disp();
B bb(13,14,15,16);
bb.fun1();
bb.A::disp();
bb.B::disp();
bb.fun2();
return 0;
}
輸出結果如下:
六、程序設計題
定義一個點類(Point)、矩形類(Rectangle)和立方體類(Cube)的層次結構。矩形包括長度和寬度兩個新數據成員,矩形的位置從點類繼承,立方體類由長度、寬度和高度構成。要求各類提供支持初始化的構造函數和顯示自己成員的成員函數。編寫主函數,測試這個層次結構,輸出立方體類的相關信息。
#include<iostream>
using namespace std;
class Point
{
public:
Point(int a,int b){x=a;y=b;}
void displayxy()
{
cout<<"The postion of point:";
cout<<"("<<x<<","<<y<<")"<<endl;
}
private:
int x,y;
};
class Rectangle:public Point
{
public:
Rectangle(int a,int b,int c,int d ):Point(a,b){i=c;j=d;}
void displayd()
{
cout<<"The length and width of rectangle:";
cout<<i<<","<<j<<endl;
}
private:
int i,j;
};
class Cube:public Rectangle
{
public:
Cube(int a,int b,int c,int d,int e):Rectangle(a,b,c,d){k=e;}
void displayk()
{
cout<<"The height of cube:"<<k<<endl;
}
private:
int k;
};
int main()
{
Cube v(20,40,3,5,6);
cout<<"The data of cube:"<<endl;
v.displayxy();
v.displayd();
v.displayk();
return 0;
}
輸出結果如下: