日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ 内存 继承

發布時間:2024/9/30 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ 内存 继承 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/randyjiawenjie/article/details/6829823


1.C++的虛函數是怎樣實現的?

??????C++的虛函數使用了一個虛函數表來存放了每一個虛函數的入口地址,這個虛函數表又使用一個虛函數指針來進行訪問。通常,虛函數指針都放在對象模型的第一個位置存放,這樣訪問徐函數指針的速度最快,沒有偏移量。通過虛函數指針,找到虛函數表,進而再做一個次偏移量計算,來得到真實虛函數的入口地址,從而訪問了虛函數。這樣看來,訪問一個虛函數將使用兩次間接計算,故要失去一些時間效率。另外,使用了虛函數,那么就要消耗一些空間,存放虛函數指針。但是,這都是值得的,為了實現多態。

2.?虛函數表是每個對象一個還是每個類一個呢?

???? 這個事搜狗的面試題目。其實討論過,我之前看到這個問題,立馬就想到了this指針。http://topic.csdn.net/u/20081031/16/6784c211-a475-4af5-a331-c3df887a2d0c.html比較詳細的討論。

??? 每個類只有若干個虛擬函數表,每個對象可以有若干個虛函數表指針。(這都是在多重繼承的情況下出現的。單重繼承的情況下,就是一個對象有一個虛函數表指針,每一個類有一個虛函數表)函數調用的時候會將this指針作為參數發過去,所以沒有必要為每一個對象做一個虛擬函數表。
???? “每個類有一個或多個虛函數表,單純的繼承下來的類有一個虛函數表,虛繼承下來的類就有可能有多個虛函數表(只是有可能),對象沒有虛函數表,但是有指向虛函數表的指針。對象之所一能調用“自己的函數”,是因為類的成員函數不知不覺的在編譯時多了一個this指針參數來識別成員數據屬于哪個對象。”

????關于這個問題,在《more effective c++》中的條款24有詳細敘述,的確是每一個類的一個虛函數表。至于放的的位置,書中也有講述。

3.函數指針和指針函數的區別?

???? 就想通過這個問題來判斷我的C水平?C語言我看的數都有三本。

??? 函數指針,一個指針,指向了函數的調用地址。? void (*fun)(void)

? 指針函數,就是一個函數的返回值是指針。 int *? fun(void)

? 這道題目我真的很冤,指針函數,我真的沒有聽說過。

?? 數組指針和指針數組我知道什么區別

4. C++ 深拷貝和淺拷貝的區別?如果要delete一個淺拷貝,需要注意什么條件?

?? 現在有一個指針p1指向了一個內存空間m1;

?? 淺拷貝就是再用一個新的指針p2指向這片內存空間m1;

?? 深拷貝就是用一個新的指針p3指向m1的副本m2

?? delete一個淺拷貝,首先要測試是不是有其它的指針還在指向這片空間。不然,直接就是野指針了。為什么野指針那么是絕對要禁止的?野指針現在指向了一片內存區間,這片內存區間以前是有意義的,現在被釋放了,操作系統可能會講這邊區間放上其它程序數據。那么,野指針仍然指向了這片區間。如果此時使用野指針,改變了這片內存的數據,那么程序應該直接崩潰。而且,這樣子的崩潰可能出現,可能等一會兒出現,不定。帶來的bug很難查找。

5.? dynamic_cast的用法?

http://blog.csdn.net/wingfiring/article/details/633033

作為四個內部類型轉換操作符之一的dynamic_cast和傳統的C風格的強制類型轉換有著巨大的差別。除了dynamic_cast以外的轉換,其行為的都是在編譯期就得以確定的,轉換是否成功,并不依賴被轉換的對象。而dynamic_cast則不然。在這里,不再討論其他三種轉換和C風格的轉換。
首先,dynamic_cast依賴于RTTI信息,其次,在轉換時,dynamic_cast會檢查轉換的source對象是否真的可以轉換成target類型,這種檢查不是語法上的,而是真實情況的檢查。
先看RTTI相關部分,通常,許多編譯器都是通過vtable找到對象的RTTI信息的,這也就意味著,如果基類沒有虛方法,也就無法判斷一個基類指針變量所指對象的真實類型, 這時候,dynamic_cast只能用來做安全的轉換,例如從派生類指針轉換成基類指針.而這種轉換其實并不需要dynamic_cast參與.
也就是說,dynamic_cast是根據RTTI記載的信息來判斷類型轉換是否合法的。

[cpp]?view plaincopy
  • struct?B1{??
  • ????virtual?~B1(){}??
  • };??
  • struct?B2{??
  • ????virtual?~B2(){}??
  • };??
  • struct?D1?:?B1,?B2{};??
  • int?main()??
  • {??
  • ????D1?d;??
  • ????B1*?pb1?=?&d;??
  • ????B2*?pb2?=?dynamic_cast<B2*>(pb1);//L1??
  • ????B2*?pb22?=?static_cast<B2*>(pb1);??//L2??
  • ????return?0;??
  • }??

  • pb2將會為NULL指針,pb22將會編譯出錯。

    [cpp]?view plaincopy
  • <span?style="font-size:16px;">??
  • </span>??
  • http://baike.baidu.com/view/1745213.htm

    dynamic_cast < type-id > (?expression?)  

    該運算符把expression轉換成type-id類型的對象。Type-id必須是類的指針、類的引用或者void*;  

    如果type-id是類指針類型,那么expression也必須是一個指針,如果type-id是一個引用,那么expression也必須是一個引用。  dynamic_cast主要用于類層次間的上行轉換和下行轉換,還可以用于類之間的交叉轉換。  

    在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的;  

    在進行下行轉換時,dynamic_cast具有類型檢查的功能,比static_cast更安全。

    http://blog.csdn.net/wingfiring/article/details/633033

    dynamic_cast 確實很好地解決了我們的問題,但也需要我們付出代價,那就是與 typeid 相比,dynamic_cast 不是一個常量時間的操作。為了確定是否能完成強制類型轉換,dynamic_cast`必須在運行時進行一些轉換細節操作。因此在使用 dynamic_cast 操作時,應該權衡對性能的影響


    5. 請閱讀以下的代碼,試試看,你能發現錯誤或者不恰當地方嗎?(提示: ? 不止一處)
    http://topic.csdn.net/t/20061129/14/5194019.html

    [cpp]?view plaincopy
  • class???Wheel{};??
  • class???Color{};??
  • ??
  • class???Car??
  • {??
  • private:??
  • ????Wheel*???wheels;??
  • public:??
  • ????Car(int???wheel_count){wheels???=???new???Wheel[wheel_count];}??
  • ????~Car(){delete???wheels;}??
  • };??
  • ??
  • class???Roadster???:???public???Car??
  • {??
  • public:??
  • ????Color???color;??
  • ??
  • ????Roadster(){};??
  • ????Roadster(const???Roadster&???rs)??
  • ????{??
  • ????????this->?color???=???rs.color;??
  • ????}??
  • ????~Roadster(){};??
  • ????Roadster&???operator=(const???Roadster&???rhs)??
  • ????{??
  • ????????this->?color???=???rhs.color;??
  • ????}??
  • ????const???Roadster&???clone()??
  • ????{??
  • ????????Roadster???the_new???=???*this;??
  • ????????return???the_new;??
  • ????}??
  • };??
  • ??
  • int???main(int???argc,???char*???argv[]){??
  • ????Roadster*???yours???=???new???Roadster;??
  • ????Roadster???mine;?????mine???=???yours->?clone();??
  • ????Car*???pCar???=???yours;??
  • ????delete???pCar;??
  • ????return???0;??
  • };???
  • 修改如下:

    [cpp]?view plaincopy
  • class???Wheel{};??
  • class???Color{};??
  • ??
  • class???Car??
  • {??
  • private:??
  • ????Wheel*???wheels;??
  • ????//1.???沒有保存wheels的下標??
  • ????//2.???最好用vector??
  • public:??
  • ????Car(int???wheel_count){wheels???=???new???Wheel[wheel_count];}??????
  • ????~Car(){delete???wheels;}??
  • ????//3.???析構函數要虛擬??
  • ????//4.???delete???wheels;???->???delete???[]wheels;??
  • ????//5.???要提供拷貝構造函數??
  • ????//6.???要重載賦值操作符??
  • };??
  • ??
  • class???Roadster???:???public???Car??
  • {??
  • public:??
  • ????Color???color;??
  • ????//7.???成員變量要私有??
  • ??
  • ????Roadster(){};??
  • ????//8.???要調用父類的構造函數??
  • ????Roadster(const???Roadster&???rs)??
  • ????{??
  • ????????this->?color???=???rs.color;??
  • ????}??
  • ????//9.???要調用父類的拷貝構造函數??
  • ????~Roadster(){};??
  • ????//10.???析構函數要虛擬(原則:析構函數要么虛擬且公有,要么保護且非虛擬)??
  • ????Roadster&???operator=(const???Roadster&???rhs)??
  • ????{??
  • ????????this->?color???=???rhs.color;??
  • ????}??
  • ????//11.???需要調用父類的賦值操作符??
  • ????//12.???沒有返回值??
  • ????//13.???返回的類型最好是const???Roadster&,???而不是Roadster&??
  • ????const???Roadster&???clone()??
  • ????{??
  • ????????Roadster???the_new???=???*this;??
  • ????????return???the_new;??
  • ????}??
  • ????//14.???不能返回局部變量的引用??
  • ????//15.???按照這里的邏輯,???其實可以直接返回*this??
  • };??
  • ??
  • int???main(int???argc,???char*???argv[]){??
  • ????//16.???這里的{}風格與前面的不一致??
  • ????Roadster*???yours???=???new???Roadster;??
  • ????Roadster???mine;?????mine???=???yours->?clone();??
  • ????//17.???最好是一行只有一條語句,???不要兩條語句放在一行??
  • ????//18.???其實這里可以直接是Roadster???mine???=???yours->?clone();??
  • ????Car*???pCar???=???yours;??
  • ????delete???pCar;??
  • ????//我認為這里是沒有問題的,作為Car類的使用者,他在這里用是沒有問題的,錯誤的只是Car類的代碼??
  • ????return???0;??
  • };???

  • 6.C++程序進入main函數之前,退出main函數之后會做些什么?

    main函數執行之前,主要就是初始化系統相關資源:
    1.設置棧指針
    2.初始化static靜態和global全局變量,即data段的內容
    3.將未初始化部分的賦初值:數值型short,int,long等為0,bool為FALSE,指針為NULL,等等,即.bss段的內容
    4.運行全局構造器,C++中構造函數
    5.將main函數的參數,argc,argv等傳遞給main函數,然后才真正運行main函數

    main 函數之后會執行相反的工作。

    總結

    以上是生活随笔為你收集整理的c++ 内存 继承的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。