1、 C++ 定義了哪些類型轉(zhuǎn)換操作符?分別有什么作用?
① 定義了四個操作符:static_cast,const_cast,dynamic_cast和reinterpret_cast。
② static_cast:可以被用于強制類型轉(zhuǎn)換(例如,non-const對象轉(zhuǎn)換為const對象,int轉(zhuǎn)換為double,等等),它還可以用于很多這樣的轉(zhuǎn)換的反向轉(zhuǎn)換(例如,void*指針轉(zhuǎn)換為有類型指針,基類指針轉(zhuǎn)換為派生類指針)。但是它不能將一個const對象轉(zhuǎn)換為一個non-const對象(只有const-cast能做到)。它最接近于C-style的轉(zhuǎn)換。
③const_cast:一般用于強制消除對象的常量性。它是唯一能做到這一點的C++風(fēng)格的強制類型。
④dynamic_cast:主要用于執(zhí)行“安全的向下轉(zhuǎn)型”。也就是說,要確定一個對象是否是一個繼承體系中的一個特定類型。它是唯一不能用舊風(fēng)格語法執(zhí)行的強制類型轉(zhuǎn)換,也是唯一可能有重大運行時代價的強制轉(zhuǎn)換。
⑤reinterpret_cast:是特意用于底層的強制轉(zhuǎn)換,導(dǎo)致實現(xiàn)依賴(implementation-dependent)(就是說,不可移植)的結(jié)果。例如,將一個指針轉(zhuǎn)型為一個整數(shù)。這樣的強制轉(zhuǎn)換在底層代碼以外應(yīng)該極為罕見。
2、 C++ 定義了哪些訪問控制關(guān)鍵字?分別有什么作用?
簡單可以歸為以下兩種描述:
1)一個類友元(包含友元函數(shù)或者友元類的成員函數(shù)或者友元類的所有成員函數(shù))可以訪問該類的任何成員(包括成員變量及成員方法)。
2)除去友元外,private成員只有該類自身的成員函數(shù)可以訪問,protected成員只有該類及其派生類的成員函數(shù)可以訪問,public成員則該類及其派生類的成員函數(shù)和對象都可以訪問。
3、 類的繼承方式和區(qū)別?
派生類繼承方式的影響
類的繼承方式有三種:private、protected、public。
1)private屬性不能被繼承。
2)
使用private繼承,父類的protected和public屬性在子類中變?yōu)?/span>private;
使用protected繼承,父類的protected和public屬性在子類中變?yōu)?/span>protected;
使用public繼承,父類中的protected和public屬性不發(fā)生改變;
4、 在什么情形下調(diào)用虛函數(shù)不會有多態(tài)性?為什么?
由虛函數(shù)實現(xiàn)的動態(tài)多態(tài)性的方法:
1. 在基類用virtual聲明成員函數(shù)為虛函數(shù)。
2. 在派生類中重新定義此函數(shù)。
3. 定義一個指向基類對象的指針變量,并使它指向同一類族中需要調(diào)用該函數(shù)的對象。
4. 通過該指針變量調(diào)用此虛函數(shù),此時調(diào)用的就是指針變量指向的對象的同名函數(shù)。
因此,總結(jié)如下:
1、基類函數(shù)未使用virtual聲明而子類中使用virtual關(guān)鍵字聲明時調(diào)用虛函數(shù)不會有多態(tài)性;
2、基類使用virtual而子類未重新實現(xiàn)該虛函數(shù)則不會有多態(tài)性;
3、 使用子類創(chuàng)建的對象轉(zhuǎn)換成基類類型調(diào)用虛函數(shù)不會有多態(tài)性;
5. 構(gòu)造函數(shù)調(diào)用順序。
class Y {...}
class X : public Y {...}
X one;
構(gòu)造函數(shù)的調(diào)用順序是下面的順序:
Y(); // 基類的構(gòu)造函數(shù)
X(); // 繼承類的構(gòu)造函數(shù)
對于多基類的情況,下面是一個例子:
class X : public Y, public Z
X one;
構(gòu)造函數(shù)以聲明的次序調(diào)用。
Y(); // 基類構(gòu)造函數(shù)首先被調(diào)用
Z();
X();
虛基類的構(gòu)造函數(shù)在任何非虛基類構(gòu)造函數(shù)前調(diào)用。如果構(gòu)造中包括多個虛基類,它們的調(diào)用順序以聲明順序為準(zhǔn)。..
如果虛類是由非虛類派生而來,那非虛類的構(gòu)造函數(shù)要先被調(diào)用。下面是一個例子:
class X : public Y, virtual public Z
X one;
調(diào)用順序如下:
Z(); // 虛基類初始化
Y(); // 非虛基類
X(); // 繼承類
下面是一個復(fù)雜的例子:
class base;
class base2;
class level1 : public base2, virtual public base;
class level2 : public base2, virtual public base;
class toplevel : public level1, virtual public level2;
toplevel view;
構(gòu)造函數(shù)調(diào)用順序如下:
base(); // 虛基類僅被構(gòu)造一次
base2();
level2(); // 虛基類
base2();
level1();
toplevel();
如果類繼承中包括多個虛基類的實例,基類只被初始化一次。
1、如果類里面有成員類,成員類的構(gòu)造函數(shù)優(yōu)先被調(diào)用;
2、創(chuàng)建派生類的對象,基類的構(gòu)造函數(shù)函數(shù)優(yōu)先被調(diào)用(也優(yōu)先于派生類里的成員類);
3、 基類構(gòu)造函數(shù)如果有多個基類則構(gòu)造函數(shù)的調(diào)用順序是某類在類派生表中出現(xiàn)的順序而不是它們在成員初始化表中的順序;
4、成員類對象構(gòu)造函數(shù)如果有多個成員類對象則構(gòu)造函數(shù)的調(diào)用順序是對象在類中被聲明的順序而不是它們出現(xiàn)在成員初始化表中的順序;
5、派生類構(gòu)造函數(shù)
作為一般規(guī)則派生類構(gòu)造函數(shù)應(yīng)該不能直接向一個基類數(shù)據(jù)成員賦值而是把值傳遞給適當(dāng)?shù)幕悩?gòu)造函數(shù)否則兩個類的實現(xiàn)變成緊耦合的(tightly coupled)將更加難于正確地修改或擴展基類的實現(xiàn)。(基類設(shè)計者的責(zé)任是提供一組適當(dāng)?shù)幕悩?gòu)造函數(shù))
6. RTTI是什么,怎么實現(xiàn)的?舉個例子。
RTTI即運行時類型識別,通過它程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對象的實際派生類型。
RTTI提供了一下兩個非常有用的操作符:
1、typeid操作符,返回指針和引用所指的實際類型
2、dynamic_cast操作符,將基類類型的指針或引用安全地轉(zhuǎn)換為派生類型的指針或引用。