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++的標準規格說明書中說到,編譯器必須要保證虛函數表的指針存在於對象實例中最前面的位置(這是爲了保證
正確取到虛函數的偏移量)。 這意味着咱們經過對象實例的地址獲得這張虛函數表,而後就能夠遍歷其中函數指針,並調用相應的函數。 函數
#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; }