1. 程式人生 > >有點意思的C/C++問題及解答:16-20

有點意思的C/C++問題及解答:16-20

問題16:在C++中定一個不能被繼承的類

       解法:容易想到的就是將這個類的建構函式和解構函式都設為私有的。這樣繼承的類就無法呼叫父類的建構函式和解構函式,編譯時就會報錯。但是不能被繼承的類如何產生物件呢?可以利用靜態函式,它與類的物件無關,可以直接通過類的作用域直接呼叫。

[cpp]  view plain copy print ?
  1. class FinalClass  
  2. {  
  3. public:  
  4.     static FinalClass* GetInstance()  
  5.     {  
  6.         return new FinalClass;  
  7.     }  
  8.    
  9.     static void DeleteInstance(FinalClass* pInstance)  
  10.     {  
  11.         delete pInstance;  
  12.         pInstance = NULL;  
  13.     }  
  14. private:  
  15.     FinalClass() {}  //私有的建構函式  
  16.     ~FinalClass() {} //私有的解構函式  
  17. };  
       問題17:設計一個類,我們只能生成該類的一個例項

    解法:其實就是設計模式中的單例模式。這裡給出兩種方式。

    方式一:類似問題16,將建構函式和解構函式定義為私有的,定義一個靜態的類物件指標。通過靜態函式進行初始化。

[cpp]  view plain copy print ?
  1. //Single.h定義  
  2. #pragma once  
  3. class Singleton    
  4. {  
  5. public:  
  6.     static Singleton* GetInstance();  
  7. private:  
  8.     Singleton();  
  9.     ~Singleton();  
  10.     static Singleton *singleton;  
  11. };  
  12. //Singleton.cpp定義  
  13. Singleton* Singleton::singleton = NULL; //靜態成員初始化  
  14. Singleton::Singleton()  
  15. {  
  16. }  
  17. Singleton::~Singleton()  
  18. {  
  19. }  
  20. Singleton* Singleton::GetInstance()  
  21. {  
  22.     if(singleton == NULL)  
  23.         singleton = new Singleton();  
  24.     return singleton;  
  25. }  

   方式二:利用區域性靜態變數只初始化一次的性質,可以這樣來實現。

[cpp]  view plain copy print ?
  1. class Singleton    
  2. {    
  3. private:       
  4.     Singleton(){}  
  5. public:                    
  6.     static Singleton* GetInstance()    
  7.     {    
  8.         static Singleton singleton; //區域性靜態變數  
  9.         return &singleton;  
  10.     }    
  11. };  

       問題18:寫一個程式,要求功能,求出用1、2、5這三個數不同個數組合的和為100的組合數。如100個1是一個組合,20個5是另外一個組合。用C++實現。

       解法:最簡單的用窮舉法,三層迴圈就可以解決了。程式碼如下,這樣效率太低了。迴圈次數為101 * 51 * 21。 這其實就是個數學問題,就是求 x + 2y + 5z = 100解的個數。變化一下,x + 5z = 100 - 2y,這個式子表明 x + 5y只能是偶數。以z為迴圈變數,有下述規律。

         z=0, x=100, 98, 96, ... 0
      z=1, x=95, 93, ..., 1
      z=2, x=90, 88, ..., 0
      z=3, x=85, 83, ..., 1
      z=4, x=80, 78, ..., 0
      ......
      z=19, x=5, 3, 1
      z=20, x=0

      因此,組合總數為100以內的偶數+95以內的奇數+90以內的偶數+...+5以內的奇數+1,
即為:(51+48)+(46+43)+(41+38)+(36+33)+(31+28)+(26+23)+(21+18)+(16+13)+(11+8)+(6+3)+1

      第二種方法的迴圈次數僅為21次。程式碼如下:

[cpp]  view plain copy print ?
  1. int C100_Solution1()  
  2. {  
  3.     int num = 0;  
  4.     for(int x = 0; x <= 100; x++)  
  5.         for(int y = 0; y <= 50; y++)  
  6.             for(int z = 0; z <= 20; z++)  
  7.                 num += ((x + 2 *y + 5 *z) == 100);  
  8.     return num;  
  9. }  
  10.   
  11. int C100_Solution2()  
  12. {  
  13.     int num = 0;  
  14.     for (int i = 0; i <= 100;i += 5)  
  15.         num += (i + 2)/2;  
  16.     return num;  
  17. }  

       問題19:實現一個strcpy函式。

       解答:看似簡單,其實考查的是基本功。需要注意這麼幾點:(1)指標為空判斷。(2)實現鏈式操作。(3)C的字串以'\0'結尾。(4)源指標加const修飾。下面給出一個實現。

[cpp]  view plain copy print ?
  1. char* strcpy(char *pDest, const char *pSrc)  
  2. {  
  3.     assert(pDest!=NULL && pSrc!=NULL);  
  4.     char* tmp = pDest;  
  5.     while((*pDest++ = *pSrc++) != '\0')  
  6.         ;  
  7.     return tmp;  
  8. }  

       問題20:static和const關鍵字儘可能多的作用。

    static關鍵字至少有下列作用: 
   (1)函式體內static變數的作用範圍為該函式體,不同於auto變數,該變數的記憶體只被分配一次,因此其值在下次呼叫時仍維持上次的值; 
  (2)在模組內的static全域性變數可以被模組內所用函式訪問,但不能被模組外其它函式訪問; 
  (3)在模組內的static函式只可被這一模組內的其它函式呼叫,這個函式的使用範圍被限制在宣告它的模組內; 
  (4)在類中的static成員變數屬於整個類所擁有,對類的所有物件只有一份拷貝; 
  (5)在類中的static成員函式屬於整個類所擁有,這個函式不接收this指標,因而只能訪問類的static成員變數。 

     const關鍵字至少有下列作用: 
  (1)欲阻止一個變數被改變,可以使用const關鍵字。在定義該const變數時,通常需要對它進行初始化,因為以後就沒有機會再去改變它了; 
  (2)對指標來說,可以指定指標本身為const,也可以指定指標所指的資料為const,或二者同時指定為const; 
  (3)在一個函式宣告中,const可以修飾形參,表明它是一個輸入引數,在函式內部不能改變其值; 
  (4)對於類的成員函式,若指定其為const型別,則表明其是一個常函式,不能修改類的成員變數; 
  (5)對於類的成員函式,有時候必須指定其返回值為const型別,以使得其返回值不為"左值"。