1多態性都有哪些?(靜態和動態,然後分別敘述了一下虛函數和函數重載)
靜態多態:編譯時多態 模板編程T a,T b 輸入a的類型不同,則運行結果不同
動態多臺:運行時多態 由虛函數實現,派生類重寫基類的成員函數,達到多態。
在基類的函數前加上virtual關鍵字,在派生類中重寫該函數,運行時將會根據對象的實際類型來調用相應的函數。如果對象類型是派生類,就調用派生類的函數;如果對象類型是基類,就調用基類的函數。這裏的多態性是指類的多態性。
2虛函數,純虛函數、抽象類
虛函數:必須實現 virtual
虛函數的工作原理:通常,編譯器處理虛函數的方法是:給每一個對象添加一個隱藏成員.隱藏成員中保存了一個指向函數地址數組的指針.這種數組稱爲虛函數表(virtual function table, vtbl).虛函數表中存儲了爲類對象進行聲明的虛函數的地址.例如,基類對象包含一個指針,訪指針指向基類中所有虛函數地址表.派生類對象將包含一個指向獨立地址表的指針.如果派生類提供了虛歲函數的新定義,訪虛函數表將保存新函數的地址;如果派生類沒有重新定義虛函數.該vtbl將保存函數原始版本的地址.如果派生類定義了新的虛函數,則該函數的地址也將被添加到vtbl中.注意,無論類中包含的虛函數是1還是10 個,都只需要在對象中添加1個地址成員,只是表的大小不同而已.
純虛函數:純虛函數在基類中不實現,在派生類中進行實現。virtual int a ( ) =0 ;它們必須在繼承類中重新聲明函數(不要後面的=0,否則該派生類也不能實例化),而且它們在抽象類中往往沒有定義。
抽象類:抽象類是指包括至少一個純虛函數的類。
3動態綁定
虛函數是類的成員,是所有的對象所共有的,因此要特殊保存虛函數也應該是類的事情,而不是對象的事情,對象只要能夠找到它們就可以了。
是這樣設計的,編譯起會爲每個有虛函數的類都創建一個虛函數表,裏面記錄着每個虛函數。另外,每個對象有一個隱含指針指向它對應的類的虛函數表。
動態綁定的調用過程是這樣的,首先,基類指針被賦值爲派生類對象的地址,那麼就可以找到指向這個類的虛函數的隱含指針,然後通過該虛函數的名字就可以在這個虛函數表中找到對應的虛函數的地址。然後進行調用就可以了。
4操作符重載(+操作符),具體如何去定義,?(讓把操作符重載函數原型說一遍)
重載操作符就是讓操作符作用域非內置類型時也有自己獨特的意義。
class person{
private:
int age;
public:
person(int a){
this->age=a;
}
inline bool operator == (const person &ps) const;
friend bool operator == (const person &ps1,const person &ps2);
};
實現方式如下:
inline bool person::operator==(const person &ps) const
{
if (this->age==ps.age)
return true;
return false;
}
友元函數實現的話沒有this指針,就會有兩個參數
bool operator ==(const person &ps1,const person &ps2)
{
return operator()
}
5內存對齊的原則?(原則敘述了一下並舉例說明) #pragma pack(x) 自定義對齊
1:數據成員對齊規則:結構(struct)(或聯合(union))的數據成員,第一個數據成員放在offset爲0的地方,以後每個數據成員存儲的起始位置要從該成員大小或者成員的子成員大小(只要該成員有子成員,比如說是數組,結構體等)的整數倍開始(比如int在32位機爲4字節,則要從4的整數倍地址開始存儲。
2:結構體作爲成員:如果一個結構裏有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲.(struct a裏存有struct b,b裏有char,int ,double等元素,那b應該從8的整數倍開始存儲.)
3:收尾工作:結構體的總大小,也就是sizeof的結果,.必須是其內部最大成員的整數倍.不足的要補齊.
typedef struct bb
{
int id; //0-3
double weight; //[8].....[15] 原則1
float height; //[16]..[19],總長要爲8的整數倍,補齊[20]...[23] 原則3
}BB;
typedef struct aa
{
char name[2]; //[0],[1]
int id; //[4]...[7] 原則1
double score; //[8]....[15]
short grade; //[16],[17]
BB b; //[24]......[47] 原則2
}AA;
int main()
{
AA a;
cout<<sizeof(a)<<" "<<sizeof(BB)<<endl;
return 0;
}
6模版怎麼實現
所謂函數模板,實際上是建立一個通用函數,其函數類型和形參類型不具體指定,用一個虛擬的類型來代表。這個通用函數就稱爲函數模板。
例如swap函數,但是不同的類型 int float double都得重新寫一遍
可以:
template<typename T>
void swap(T &a,T &b)
{
T t;
t = a;
a = b;
b = t;
}
這樣輸入不一樣的值就自動轉換了。
7指針和const的用法?(誰在前面誰不能變,倆const包*的話都不能變)
const int *p; 常量指針 變量值不能改變
int *const p; 指針常量 指針值不能改變
const int *const ptr; 兩個const的是值和指針都不能改變
int const *const ptr;
8爲什麼基類的析構函數要定義成析構函數?
意思是不是虛函數的話,在進行析構的時候會調用基類的析構函數,而不是派生類的析構函數,會造成內存泄漏。
9內聯函數、宏定義(提高函數的執行效率,適用於小並且用的頻率高的函數)
內聯函數:在定義前加上inline,在申明前加沒用哦!
優點:提高執行效率(調用函數花費大於函數處理)
缺點:代碼過長不適合
複雜的函數不適合
inline int max (int a,int b) //只有都在申明前有沒用的!!!
inline int max(int a, int b)
{
return a > b ? a : b;
}
———————————————————————————————————————————
宏定義缺點:1容易出錯,在預處理會產生邊際效應
2 不可調試
#define MAX(a,b) (a) > (b) ? (a):(b) !!! 注意括號
10 const typedef #define(主要講了const的用處,有那些優點)
const:可以指定類型,進行類型檢測 會分配空間,可以調用 ,他是在運行才分配空間啥的,可以調試出來
typedef: 只是一個別名 不分配空間 typedef INT int
#define(#define #undef):無法對宏定義中的變量進行類型檢查,它是在預編譯前就搞好了,出錯了也不知道
11 extern ,static
extern + 函數/變量 ==該函數或者變量是全局的
static :相反,只能在本模塊中用
12 排序算法大集合
排序法 |
最差時間分析 | 平均時間複雜度 | 穩定度 | 空間複雜度 |
冒泡排序 | O(n2) | O(n2) | 穩定 | O(1) |
快速排序 | O(n2) | O(n*log2n) | 不穩定 | O(log2n)~O(n) |
選擇排序 | O(n2) | O(n2) | 穩定 | O(1) |
二叉樹排序 | O(n2) | O(n*log2n) | 不一頂 | O(n) |
插入排序 |
O(n2) | O(n2) | 穩定 | O(1) |
堆排序 | O(n*log2n) | O(n*log2n) | 不穩定 | O(1) |
希爾排序 | O | O | 不穩定 | O(1) |
void quickSort(int s[], int l, int r) //快排
{
if (l< r)
{
int i = l, j = r, x = s[l];
while (i < j)
{
while(i < j && s[j]>= x) // 從右向左找第一個小於x的數
j--;
if(i < j && s[j] < x)
s[i++] = s[j];
while(i < j && s[i]< x) // 從左向右找第一個大於等於x的數
i++;
if(i < j && s[i] >= x)
s[j--] = s[i];
}
s[i] = x;
quickSort(s, l, i - 1); // 遞歸調用
quickSort(s, i + 1, r);
}
}
void quickSort(int a[],int r, int l)
{
if(r < l)
{
int i = l , j = l , x = s[l];
while(i < j)
{
while(i < j && s[j] >= x)
j --;
if(i < j && s[j]<x)
s[i++] = s[j];
while(i < j && s[i] <= x)
i++;
if(i < j && s[i]>=x)
s[j--] = s[i];
}
s[i] = x;
quickSort(s,l,i-1);
quickSort(s,i+1,r);
}
}
void bubble(int *pdata,int length)
{
for(int i = 0 ;i < length;i++)
{
for(int j = 0; j < length -i - 1;j++)
{
if(pdata[j]>data[j+1])
swap(pdata[j],pdata[j+1]);
}
}
}