C/C++基礎面試題集錦

1.#include<>與#include""的區別
當用#include「file.h」時,先搜索當前工做目錄,若是沒有,再去搜索庫,庫沒有再搜索資源庫;
當用#include<file.h>時,編譯器先從標準庫路徑開始搜索,若是沒再搜索資源庫目錄,最好搜索當前工做目錄。
2.在C++ 程序中調用被 C 編譯器編譯後的函數,爲何要加 extern 「C」聲明?
C++支持函數重載,而過程式語言C則不支持。函數被C++編譯後在符號庫中的名字與C語言的不一樣。例如,假設某個函數的原型爲:該函數被C編譯器編譯後在符號庫中的名字爲_foo,而
C++編譯器則會產生像_foo_int_int之類的名字,foo_int_int 這樣的名字包含了函 數名、函數參數數量及類型信息,C++就是靠這種機制來實現函數重載的。例如,在C++中,函數
void foo( int x, int y )void foo( int x, float y )編譯生成的符號是不相同的,後者 _foo_int_float
3.虛函數的實現機制

4.什麼函數不能聲明爲虛函數: html

一個類中將全部的成員函數都儘量地設置爲虛函數老是有益的。 
設置虛函數須注意: 
1:只有類的成員函數才能說明爲虛函數; 
2:靜態成員函數不能是虛函數; 
3:內聯函數不能爲虛函數; 
4:構造函數不能是虛函數; 
5:析構函數能夠是虛函數,並且一般聲明爲虛函數。
ios

5.float與0值比較 c++

const float EPSINON = 0.00001; 
if ((x >= - EPSINON) && (x <= EPSINON)
程序員

6.頭文件中的 ifndef/define/endif 幹什麼用 面試

7.虛函數 數組

對C++ 瞭解的人都應該知道虛函數(Virtual Function)是經過一張虛函數表(Virtual Table)來實現的。簡稱爲V-Table。 在這個表中,主是要一個
類的虛函數的地址表,這張表解決了繼承、覆蓋的問題,保證其容真實反應實際的函數。這樣,在有虛函數的類的實例中這個表被分配在了 這個實例的
內存中,因此,當咱們用父類的指針來操做一個子類的時候,這張虛函數表就顯得由爲重要了,它就像一個地圖同樣,指明瞭實際所應該調用的函數。
這裏咱們着重看一下這張虛函數表。在C++的標準規格說明書中說到,編譯器必須要保證虛函數表的指針存在於對象實例中最前面的位置(這是爲了保證
正確取到虛函數的偏移量)。 這意味着咱們經過對象實例的地址獲得這張虛函數表,而後就能夠遍歷其中函數指針,並調用相應的函數。
函數

虛函數 是一種特殊的虛函數,它的通常格式以下:
class <類名>
{
virtual <類型><函數名>(<參數表>)=0;
};
在許多狀況下,在 基類 中不能對虛函數給出有意義的實現,而把它聲明爲純虛函數,它的實現留給該基類的 派生類 去作。這就是純虛函數的做用。
純虛函數可讓類先具備一個操做名稱,而沒有操做內容,讓派生類在繼承時再去具體地給出定義。凡是含有純虛函數的類叫作 抽象類 。這種類不能聲明對象,只是做
爲基類爲派生類服務。除非在派生類中徹底實現基類中全部的的純虛函數,不然,派生類也變成了抽象類,不能實例化對象。
8.c++ private protected public
當private,public,protected單純的做爲一個類中的成員權限設置時:
private: 只能由該類中的函數、其友元函數訪問,不能被任何其餘訪問,該類的對象也不能訪問. 
protected: 能夠被該類中的函數、子類的函數、以及其友元函數訪問,但不能被該類的對象訪問 
public: 能夠被該類中的函數、子類的函數、其友元函數訪問,也能夠由該類的對象訪問
注:友元函數包括兩種:設爲友元的全局函數,設爲友元類中的成員函數
當private,public,protected做爲繼承方式時:
對於公有繼承方式: 
(1)父類的public成員成爲子類的public成員,容許類之外的代碼訪問這些成員;
(2)父類的private成員仍舊是父類的private成員,子類成員不能夠訪問這些成員;
(3)父類的protected成員成爲子類的protected成員,只容許子類成員訪問;
9.友元函數
include <iostream>
using namespace std;
class Car
{
    friend void display(Car); //類"Car"的朋友display() //友元函數的聲明
private:
    int speed;
    char color[20];
public:
    void input( )
    {
        cout<<"Enter the color : ";
        cin>>color;
        cout<<"Enter the speed : ";
        cin>>speed;
    }
};
void display(Car x) //友元函數的定義
{
    cout<<"The color of the car is : "<<x.color<<endl;
    cout<<"The speed of the car is : "<<x.speed<<endl;
}
int main( )
{
    Car mine;
    mine.input( ); //訪問成員函數
    display(mine); //友元函數的使用 //將對象"mine"傳給友元函數
    return 0;
}
10.int* pInt = new int(5);和int* pInt = new int[5]; 
int *p = new int(5); 
這句是從堆上分配一個int型變量所佔的字節內存,這個內存單元存放的整數值爲5,而後讓一個整形的指針變量p指向它的地址。
釋放方式:delete p;
int *p = new int[5]; 
這句至關於從堆上分配一個含有5個元素的整形數組所佔的字節內存,而後讓一個整形的指針變量p指向它的首址。
釋放方式:delete []p;(注意這個[]不能掉了,若是掉了就會只釋放P[0]所佔的空間,p[1]到p[4]不會被釋放,產生內存泄露。)
 

GetMemory函數詳解

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std; spa

char *GetMemory(char *&p, int num)
{
p = (char *)malloc(sizeof(char)*num); 指針

//p = new char[num];
return p; htm

}
int main(void)
{
char *str ;
GetMemory(str, 100);
strcpy(str, "hello");
cout << str << endl;
return 0;
}

//上面是一個正確的程序,下面是轉載的一些相關的知識

GetMemory錯誤講解(指針練習) 錯誤程序:

void GetMemory( char *p )
{
 p = (char *) malloc( 100 );
}
void Test( void ) 
{
 char *str = NULL;
 GetMemory( str ); 
 strcpy( str, "hello world" );
 printf( 「%s」,str );
}

這個一個考驗對指針理解的題目,上面程序在運行以後:

1,調用GetMemory( str )後, str並未產生變化,依然是NULL.只是改變的str的一個拷貝的內存的變化   

2,strcpy( str, "hello world" );程序運行到這將產生錯誤。

3,new的時候有可能內存出錯,應該在*p = (char *) malloc( num ); 後判斷內存是否申請成功,應加上:
     if ( *p == NULL )
   {
     ...//進行申請內存失敗處理
   }

4,動態建立的內存沒釋放。

錯誤分析:

       錯認爲 GetMemory(char   *p)中的 p 「就是」 GetMemory(str)中的str。但p「不是」str,它只是「等於」str 。 
就象:   int   a   =   100;   
            int   b   =   a;       //   如今b等於a   
            b   =   500;         //   如今能認爲a   =   500 ?      
顯然不能認爲a   =   500,由於b只是等於a,但不是a! 當b改變的時候,a並不會改變,b就不等於a了。    所以,雖然p已經有new的內存,但str仍然是null  


GetMemory(str);             //把str傳進去,str是一個指針,而他其實是一個int      
void   GetMemory(char   *p)     //   p是str的一個副本   
{   
p=(char   *)new   char[100];         //   p的值改變,可是str的值並無改變。   
}   
而雙重指針爲何就能夠了呢:   
GetMemory(&str);             //把str的地址傳進去       
void   GetMemory(char   **   p)     //   p是str地址的一個副本   
{  

    *p   =   (char   *)new   char[100];         //   p指向的值改變,也就是str的值改變。   
}

修改方法1:(推薦使用這種方法)

void GetMemory2(char **p)變爲二級指針. 
void GetMemory2(char **p, int num) 

*p = (char *)malloc(sizeof(char) * num); 

void Test(void)

char *str=NULL; 
GetMemory=(&str); 
strcpy(str,"hello world"); 
printf(str); 
}

修改方法2:

char *GetMemory()

char *p=(char *)malloc(100); 
return p; 

void Test(void){ 
char *str=NULL; 
str=GetMemory();
strcpy(str,"hello world"); 
printf(str); 
}

附錄A(相關資料)

試題5:
char *GetMemory( void )

 char p[] = "hello world"; 
 return p; 
}

void Test( void )

 char *str = NULL; 
 str = GetMemory(); 
 printf( str ); 

試題6:
void GetMemory( char **p, int num )
{
 *p = (char *) malloc( num );
}

void Test( void )
{
 char *str = NULL;
 GetMemory( &str, 100 );
 strcpy( str, "hello" ); 
 printf( str ); 

 試題7:

void Test( void )
{
 char *str = (char *) malloc( 100 );
 strcpy( str, "hello" );
 free( str ); 
 ... //省略的其它語句
}

解答:

試題5中
char p[] = "hello world"; 
return p; 
的p[]數組爲函數內的局部自動變量,在函數返回後,內存已經被釋放。這是許多程序員常犯的錯誤,其根源在於不理解變量的生存期。

試題6中
一、GetMemory避免了試題4的問題,傳入GetMemory的參數爲字符串指針的指針,可是在GetMemory中執行申請內存及賦值語句
*p = (char *) malloc( num ); 
後未判斷內存是否申請成功,應加上:
if ( *p == NULL )
{
 ...//進行申請內存失敗處理

二、試題6的Test函數中也未對malloc的內存進行釋放。

試題7中
    存在與試題6一樣的問題,在執行
char *str = (char *) malloc(100); 後未進行內存是否申請成功的判斷;另外,在free(str)後未置str爲空,致使可能變成一個「野」指針,應加上: str = NULL; 

  剖析:

  試題4~7考查面試者對內存操做的理解程度,基本功紮實的面試者通常都能正確的回答其中50~60的錯誤。可是要徹底解答正確,卻也絕非易事。

  對內存操做的考查主要集中在:

  (1)指針的理解;

  (2)變量的生存期及做用範圍;

  (3)良好的動態內存申請和釋放習慣。

  再看看下面的一段程序有什麼錯誤:

swap( int* p1,int* p2 )
{
 int *p;
 *p = *p1;
 *p1 = *p2;
 *p2 = *p;
}

  在swap函數中,p是一個「野」指針,有可能指向系統區,致使程序運行的崩潰。在VC++中DEBUG運行時提示錯誤「Access Violation」。該程序應該改成:

swap( int* p1,int* p2 ) {  int p;  p = *p1;  *p1 = *p2;  *p2 = p; }

相關文章
相關標籤/搜索