經典C++筆試題

1、判斷

void main(){  
    char str1[] = "abc";  
    char str2[] = "abc";  
    const char str3[] = "abc";  
    const char str4[] = "abc";  
    const char* str5 = "abc";  
    const char* str6 = "abc";  
    std::cout << std::boolalpha << ( str1==str2 ) << std::endl; //false  
    std::cout << std::boolalpha << ( str3==str4 ) << std::endl; // false  
    std::cout << std::boolalpha << ( str5==str6 ) << std::endl; // true  
    /*分別輸出字符串的地址 
    str1,str2,str3,str4位於棧區,向低地址增長 
    str5,str6位於只讀數據區,所以地址相同 
    */  
    printf("%p\t%p\n",str1,str2);  
    printf("%p\t%p\n",str3,str4);  
    printf("%p\t%p\n",str5,str6);  
    system("pause");  
}

解答:分別輸出false,false,true

str1和str2都是字符數組,每個都有自己的存儲器,數組名的值則是各存儲器的首地址,所以不等。

str3和str4同上,只是按const語義,他們所指向的數據區不能修改

str5和str6不是數組而是字符指針,並沒有分別存儲器,"abc"以常量形式存於靜態數據區,指針則指向該區的首地址,所以相等。


2、  將 str 中的小寫字母轉換成大寫字母

void UpperCase( char str[] )                                         
{
    for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
        if( 'a'<=str[i] && str[i]<='z' )
            str[i] -= ('a'-'A' );
}
UpperCase函數傳遞指針,sizeof(str)==4,字符串長度超過4,就不能夠轉換

3、非C++內建型別A和B, 在哪幾種情況下B能隱式轉化爲A?

  1. // Case 1 : B公有繼承自A  
  2. class B : public A  
  3. {  
  4.     ...  
  5. }  

  1. // Case 2 : B實現了隱式轉化爲A的轉化  
  2. class B   
  3. {  
  4.     operator A();  
  5. }  
  1. // Case 3 : A實現了non-explicit的參數爲B的構造函數  
  2. class A   
  3. {  
  4.     A(const B&);  
  5. }  
  1. // Case 4 : 賦值操作  
  2. A & operator=(const A&);  

5、c++空類默認產生的類成員函數
//c++空類默認產生的類成員函數
class Empty
{
public:
Empty();//缺省構造函數
Empty(const Empty&);//拷貝構造函數
~Empty();//析構函數
Empty& operator=(const Empty&);//賦值運算符
Empty* operator&();//取址運算符
const Empty* operator&() const;//取址運算符const 


6判斷
//1以整數形式存放和以浮點形式存放其內存數據是不一樣的,因此兩者不等
float a = 1.0f;
cout<<(int)a<<endl;//實際上是以浮點數 a爲參數構造了一個整型數1,
cout<<(int&)a<<endl;//告訴編譯器將a當作整數看(並沒有做任何實質上的轉換)

//0以整數形式存放和以浮點形式存放其內存數據是一樣的,因此兩者相等
float b = 0.0f;
cout<<(int)b<<endl;
cout<<(int&)b<<endl;


7、定義 int **a[3][4], 則變量佔有的內存空間爲:_____ ?
分析:由於優先級[]>*,所以a是存放二級指針的二維數組;
若(**a)[3][4],則a爲指向二維數組的指針;


4、判斷

struct Test
{
Test(int){}
Test(){}
void fun(){}
};

        Test a(1);
a.fun();
Test b();//Error,默認構造函數初始化不加括號
b.fun();


8、數組和指針的區別

數組可以再靜態存儲區和棧上建立,指針可以指向任意類型的存儲塊

9、判斷輸出

main()
{
char *p1=“name”;
char *p2;
p2=(char*)malloc(20);
memset (p2, 0, 20);
while(*p2++ = *p1++);
printf(“%s\n”,p2);//p2指向字符串末端,爲空
}

10使用strcat()

main()
{
char *p1;
char *p2;
p1=(char *)malloc(25);
p2=(char *)malloc(25);
strcpy(p1,”Cisco”);
strcpy(p2,“systems”);
strcat(p1,p2);//注意空間的處理
printf(“%s”,p1);
}
儘管給p1,p2都分配了25字節的內存,但是使用strcat可以將函數連接在一起

11有哪幾種情況只能用intialization list而不能用assignment?

當類中含有 const、reference 成員變量;基類的構造函數都需要初始化表。

12、初始化vector

vector< vector<int>> ivv;

ivv[0].push_back(1);

cout<<ivv[0][0]<<endl;

-----------------------------代碼錯誤,沒有初始化vector<int>就使用

vector<vector<int>> ivv;

ivv.push_back(vector<int>());

ivv[0].push_back(1);

cout<<ivv[0][0]<<endl;

------------------------------可以使用vector<vector<int>> ivv(10);進行多數的初始化


13.繼承的優缺點

1、類繼承是在編譯時刻靜態定義的,且可直接使用,
2、類繼承可以較方便地改變父類的實現。(對於子類改變父類的實現)
缺點:
1、因爲繼承在編譯時刻就定義了,所以無法在運行時刻改變從父類繼承的實現
2、父類通常至少定義了子類的部分行爲,父類的任何改變都可能影響子類的行爲
3、如果繼承下來的實現不適合解決新的問題,則父類必須重寫或被其他更適合的類替換。
這種依賴關係限制了靈活性並最終限制了複用性。


14、c++在頭文件中進行類的聲明,在對應的實現文件中進行類的定義有什麼意義?

h爲編譯器提供一個索引,連接obj對象和主程序
編譯器在編譯的時候,如果需要,則去查找h,找到了h,再找對應的obj,就可以找到類的方法了
但是如果直接寫入到同一個文件(例如hpp),主程序沒有索引,也不清楚具體的類實現了沒有,只能一次次重複的編譯相同的代碼,這樣實際上沒有把這個類該有的東西抽象出來


發佈了44 篇原創文章 · 獲贊 7 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章