C++學習(47)

王小東大將軍發表於2017-06-16

1.

如果一個類中宣告瞭純虛擬函式,其派生類中沒有對該函式定義,那該函式在派生類中仍為純虛擬函式,凡是包含純虛擬函式的類都是抽象類。

 

通常過載函式呼叫的依據是函式名、引數型別、引數個數

 

類的靜態成員是屬於類的而不是屬於哪個物件的,因此可以說是所有物件所共有的。

 

行內函數是在編譯時將目的碼插入的。

 

2.假設下面函式foo會被多執行緒呼叫,那麼讓i、j、k三個變數哪些因為執行緒間共享訪問需要加鎖保護(i、j)

int i=0;
void foo() {
    static int j=0;
    int k=0;
    i++;j++;k++;
}

分析:多執行緒呼叫時要進行保護時,主要是針對全域性變數和靜態變數的,函式內的區域性變數不會受到影響。

這裡i是全域性變數,j是區域性靜態變數,所以要進行保護。

 

每個執行緒都有一個棧,儲存自己的區域性變數;多執行緒需要程式設計師考慮全域性變數和靜態變數的保護。

 

可重入函式要求不能使用無保護的全域性變數,所以i需要加鎖,k為區域性變數不用,j前加了static,static其中一個作用就是:延長變數的生存期,使其具有全域性變數的作用,所以j也需要加鎖。

 

3.

1) malloc 函式: void *malloc(unsigned int size)

在記憶體的動態分配區域中分配一個長度為size的連續空間,如果分配成功,則返回所分配記憶體空間的首地址,否則返回NULL,申請的記憶體不會進行初始化

 

2)calloc 函式: void *calloc(unsigned int num, unsigned int size)

按照所給的資料個數和資料型別所佔位元組數,分配一個num * size 連續的空間。

 

calloc申請記憶體空間後,會自動初始化記憶體空間為 0,但是malloc不會進行初始化,其記憶體空間儲存的是一些隨機資料。

 

3)realloc 函式: void *realloc(void *ptr, unsigned int size)

動態分配一個長度為size的記憶體空間,並把記憶體空間的首地址賦值給ptr,把ptr記憶體空間調整為size。

申請的記憶體空間不會進行初始化

 

4)new是動態分配記憶體的運算子,自動計算需要分配的空間,在分配類型別的記憶體空間時,同時呼叫類的建構函式,對記憶體空間進行初始化,即完成類的初始化工作。動態分配內建型別是否自動初始化取決於變數定義的位置,在函式體外定義的變數都初始化為0,在函式體內定義的內建型別變數都不進行初始化。

 

4. 兩個指標變數之間的運算

只有指向同一陣列的兩個指標變數之間才能進行運算,否則運算毫無意義。

 

1) 兩指標變數相減:

兩指標變數相減所得之差是兩個指標所指陣列元素之間相差的元素個數。實際上是兩個指標值(地址)相減之差再除以該陣列元素的長度(位元組數)。例如pf1和pf2是指向同一浮點陣列的兩個指標變數,設pf1的值為2010H,pf2的值為2000H,而浮點陣列每個元素佔4個位元組,所以pf1-pf2的結果為(2000H-2010H)/4=4,表示pf1和 pf2之間相差4個元素。

 

注意:兩個指標變數不能進行加法運算。例如,pf1+pf2是什麼意思呢?毫無實際意義。

 

2) 兩指標變數進行關係運算

指向同一陣列的兩指標變數進行關係運算可表示它們所指陣列元素之間的關係。例如:pf1==pf2 表示pf1和pf2指向同一陣列元素;pf1>pf2 表示pf1處於高地址位置;pf1<pf2 表示pf2處於低地址位置。

指標變數還可以與0比較。設p為指標變數,則p==0表明p是空指標,它不指向任何變數;p!=0表示p不是空指標

 

空指標是由對指標變數賦予0值而得到的。例如:#define NULL 0 int *p = NULL;

 

對指標變數賦0值和不賦值是不同的指標變數未賦值時,值是隨機的,是垃圾值,不能使用的,否則將造成意外錯誤。而指標變數賦0值後,則可以使用,只是它不指向具體的變數而已。

 

5.分析下列程式碼如何修改程式提供編譯?C

template <classT>
struct sum {
    static void foo(T op1, Top2) {
        cout<<op1 <<op2;
    }
};sum::foo(1,3);

A 編譯通過 B應該去掉static關鍵字 C 呼叫應該如下sum<int> :: foo(1,3) D呼叫應該如下 sum::<int> foo(1,3) 

分析:這道題的考點是類别範本的static成員。首先說說模板例項化,即類别範本需要指定確定的型別,例如本題中sum<int> a或者sum<string> a等。static成員函式可以由類名或者物件直接呼叫。在本題中,以下兩種形式均可:

sum<int> a;

a.foo(1,3);

或者

sum<int>::foo(1,3);

 

分析二:

template<classT>struct sum{
static void foo(T op1 , T op2){
cout << op1 <<op2;
}
};
sum<int>::foo(1,3);


6.分析下列程式,執行結果是at

#include<stdio.h>
main() {
    char*a[]={"work","at","alibaba"};
    char **pa=a;
    pa++;
    printf("%s",*pa);
}

分析:a -> work

a+1 -> at

a+2  -> alibaba

char* *pa=a; pa是一個指向a的指標

pa++ 指向a的下一個即a+1

 

補充:

#include<iostream>
using namespacestd;
int main() {
    char*a[]={"work","at","alibaba"};
    char **pa=a;
    cout<<a<<""<<*a<<" "<<pa<<""<<*pa<<endl;
    pa++;
    cout<<*pa<<endl;
}


7. 如果只是論一個漢字佔用的位元組數,那麼UTF-8 佔用3個位元組, UTF-16 佔用2個位元組。但是如果儲存文字的話,需要在文字使用EF BB BF 三個位元組表示使用UTF-8 編碼,使用FE FF 表示使用 UTF-16 編碼

 

UTF-16 固定表示兩個位元組表示一個字元,不管是字母還是漢字;UTF-8使用1-3個位元組表示一個字元

0xxxxxxx 一個位元組相容ASCII,能表示127個字元 110xxxxx 10xxxxxx.如果是這樣的格式,則把兩個位元組當一個字元 1110xxxx 10xxxxxx 10xxxxxx 如果是這種格式則是三個位元組當一個字元

 

所以,UTF-8的空間是根據儲存的內容不同而不同。如果儲存的漢字多,使用 UTF-16 佔用字元數雙倍的空間,使用 UTF-8 佔用字元數三倍的空間;如果儲存的英文字母多,使用 UTF-16 使用字元數雙倍的空間,使用 UTF-8 使用字元數相同的空間。

 

8.C++物件導向程式語言中,以下不正確的是:

A 介面中可以用虛方法

B 一個類可以實現多個介面

C 介面不能被例項化

D 介面中可以包含已經實現的方法

 

分析: 這道題正確答案AD,首先所謂的介面是指只包含純虛擬函式的抽象類,和普通的抽象類含不一樣。所以A不對,必須是純虛擬函式。然後B是正確的沒有問題。然後是C,剛才說介面是特殊的抽象類,抽象類的唯一左右就是建立派生類,不能定義抽象類的物件,所以C是正確的。對於D,介面即只包含純虛擬函式的抽象類,所以D是不對的.

 

本道題A,純虛擬函式是虛擬函式的一種,所以A應該也是正確的。

C++中沒有介面的概念,用抽象類表示介面,抽象類可以包含實現的虛方法。

 

分析二:這題有點問題。c++沒有介面的概念,用抽象類來表示介面,抽象類可以包含實現的虛方法

介面:介面是一個概念。它在C++中用抽象類來實現。

 

抽象類和介面的區別

抽象類實現的具體方法預設為虛的,但實現介面的類中的介面方法卻預設為非虛的,當然您也可以宣告為虛的。

虛方法當然可以是實現。

 

所以這題不是很嚴謹

程式設計角度,介面只是包含純虛擬函式的抽象類,並不是說只能包含純虛擬函式。AD是沒問題的。

但是如果約定好只包含純虛擬函式,那D就錯了,A還有待商榷