1.在C++ 程序中調用被C 編譯器編譯後的函數,爲何要加extern 「C」?html
答:C++語言支持函數重載,C 語言不支持函數重載。函數被C++編譯後在庫中的名字與C 語言的不一樣。假設某個函數的原型爲: void foo(int x, int y);c++
該函數被C 編譯器編譯後在庫中的名字爲_foo , 而C++ 編譯器則會產生像_foo_int_int 之類的名字。編程
C++提供了C 鏈接交換指定符號extern「C」來解決名字匹配問題。數組
http://yjbys.com/bishi/timu/598258.html安全
2.char * strcpy(char * strDest,const char * strSrc);ide
1
2
3
4
5
6
7
8
9
|
⒈
strcpy
的實現代碼
char
*
strcpy
(
char
* strDest,
const
char
* strSrc)
{
if
((NULL==strDest) || (NULL==strSrc))
//[1]
throw
"Invalid argument(s)"
;
//[2]
char
* strDestCopy = strDest;
//[3]
while
((*strDestCopy++=*strSrc++)!=
'\0'
);
//[4]
return
strDest;
}
|
C++多態性是經過虛函數來實現的,虛函數容許子類從新定義成員函數,而子類從新定義父類的作法稱爲覆蓋(override),或者稱爲重寫。(這裏我以爲要補充,重寫的話能夠有兩種,直接重寫成員函數和重寫虛函數,只有重寫了虛函數的才能算做是體現了C++多態性)而重載則是容許有多個同名的函數,而這些函數的參數列表不一樣,容許參數個數不一樣,參數類型不一樣,或者二者都不一樣。編譯器會根據這些函數的不一樣列表,將同名的函數的名稱作修飾,從而生成一些不一樣名稱的預處理函數,來實現同名函數調用時的重載問題。但這並無體現多態性。模塊化
多態與非多態的實質區別就是函數地址是早綁定仍是晚綁定。若是函數的調用,在編譯器編譯期間就能夠肯定函數的調用地址,並生產代碼,是靜態的,就是說地址是早綁定的。而若是函數調用的地址不能在編譯器期間肯定,須要在運行時才肯定,這就屬於晚綁定。函數
那麼多態的做用是什麼呢,封裝可使得代碼模塊化,繼承能夠擴展已存在的代碼,他們的目的都是爲了代碼重用。而多態的目的則是爲了接口重用。也就是說,不論傳遞過來的到底是那個類的對象,函數都可以經過同一個接口調用到適應各自對象的實現方法。url
最多見的用法就是聲明基類的指針,利用該指針指向任意一個子類對象,調用相應的虛函數,能夠根據指向的子類的不一樣而實現不一樣的方法。若是沒有使用虛函數的話,即沒有利用C++多態性,則利用基類指針調用相應的函數的時候,將總被限制在基類函數自己,而沒法調用到子類中被重寫過的函數。由於沒有多態性,函數調用的地址將是必定的,而固定的地址將始終調用到同一個函數,這就沒法實現一個接口,多種方法的目的了。spa
虛函數理解:
對於虛函數調用來講,每個對象內部都有一個虛表指針,該虛表指針被初始化爲本類的虛表。因此在程序中,無論你的對象類型如何轉換,但該對象內部的虛表指針是固定的,因此呢,才能實現動態的對象函數調用,這就是C++多態性實現的原理。
總結(基類有虛函數):
一、 每個類都有虛表。
二、 虛表能夠繼承,若是子類沒有重寫虛函數,那麼子類虛表中仍然會有該函數的地址,只不過這個地址指向的是基類的虛函數實現。若是基類3個虛函數,那麼基類的虛表中就有三項(虛函數地址),派生類也會有虛表,至少有三項,若是重寫了相應的虛函數,那麼虛表中的地址就會改變,指向自身的虛函數實現。若是派生類有本身的虛函數,那麼虛表中就會添加該項。
三、 派生類的虛表中虛函數地址的排列順序和基類的虛表中虛函數地址排列順序相同。
http://blog.csdn.net/youngchang06hpu/article/details/8715011
4. 引用與指針
http://blog.csdn.net/youngchang06hpu/article/details/8715011
參考:《c和指針》
1 引用是C++中的概念,C中沒有引用,而只有&操做,即取地址符,其必須做用於一個左值。
2 引用是變量的一個別名,即創建引用並不會致使新內存的分配,引用在初始化時必須存在一個對應的被引用的內存對象,且此引用關係創建後,引用不能再被改變,而所引用的變量是能夠改變的。
3 引用在參數傳遞中使用,下降了傳值傳遞的消耗。若是引用做爲函數的返回值,那麼函數能夠做爲一個左值來使用。這一點在C++的流操做部分很常見。
int a[5]={1,2,3,4,5};
int *p1=(int*)(&a+1);
int *p2=(int*)((int)a+1);
int *p3=(int*)(&a)+1;
// p3=p3+1;
printf("%x,%x,%x",p1[-1],*p2,p3[-1]);
執行結果爲 5,2000000,1。對於結果5仍是比較糾結。看了一下網上的帖子和幾本書,總結了一下。
首先說一下關於對數組名取地址:
關於對數組名取地址的問題,因爲數組名是右值,原本&array 是不合法的,早期很多編譯器就是指定&array 是非法的,但後來C89/C99認爲數組符合對象的語義,對一個對象取地址是合理的,所以,從維護對象的完整性出發,也容許&array 。只不過,&array 的意義並不是對一個數組名取地址,而是對一個數組對象取地址,也正由於如此,array 纔跟&array 所表明的地址值同樣,同時sizeof(array )應該跟sizeof(&array )同樣,由於sizeof(&array )表明取一個數組對象的長度。
要注意到 array 和 &array 的類型是不一樣的。array爲一個指針,而&array是指向數組int [100]的指針。array 至關於 &array[0],而 &array 是一個指向 int[100] 的指針,類型是 int(*)[100]。
另外從步長的角度分析這個問題
執行以下語句:
printf("array=%p, array+1=%p/n", array, array+1);
printf("&array=%p, &array+1=%p/n", &array, &array+1);
結果爲:
array=0012FDF0, array+1=0012FDF4 //+sizeof(int)
&array=0012FDF0, &array+1=0012FF80 //+sizeof(&array)
在《C專家編程》書中關於數組一章P203,有以下解釋: 不管指針仍是數組,在連續的內存地址上移動時,編譯器都必須計算每次前進的步長。 編譯器自動把下標值調整到數組元素大小,對起始地址進行加法操做以前,編譯器都會負責計算每次增長的步長,這就是爲何指針類型老是有類型限制,每一個指針只能指向一種類型的緣由所在,由於編譯器須要知道對指針進行解除引用操做時應該取幾個字節,以及每一個小標的步長應取幾個字節。 另外步長的自動調整還和上下語句相關: int *p3=(int*)(&a); p3=p3+1; 首先對P3指針變量賦初值,指向數組int [5]的指針,而後對指針進行加一的操做,其中P3定義爲一個指向int類型的指針,所以最終P3的值等價P3+sizeof(int) int *p3=(int*)(&array+1); &array+1,步長爲1,其中步長的長度和&array的類型匹配,即&array是指向數組int [100]的指針,因此&array+1等價爲&array+sizeof(&array) 最終p1[-1]等價爲*(P1-1),所以等價爲第二個int [5]的數據首地址(並不存在第二個數組顯然當前指針已經越界了,另外數組元素在內存中是連續存貯的)減去一個爲sizeof(int)的步長,因此指向了第一個數組的最後1個元素。