• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Benjamin

            靜以修身,儉以養(yǎng)德,非澹薄無以明志,非寧靜無以致遠(yuǎn)。
            隨筆 - 397, 文章 - 0, 評(píng)論 - 196, 引用 - 0
            數(shù)據(jù)加載中……

            C++之virtual functions(虛函數(shù))實(shí)現(xiàn)細(xì)節(jié)及相關(guān)概念

            c++中的(static) type和 (dynamic) type 概念是基于多態(tài)(polymorphism) ,例如:Vehicle*指針如果實(shí)際是指向一個(gè)Car對(duì)象,那么這個(gè)指針的靜態(tài)類型就是Vechicle,Car則是他的動(dòng)態(tài)類型。靜態(tài)類型發(fā)生在編譯器編譯時(shí),動(dòng)態(tài)類型發(fā)生在動(dòng)態(tài)綁定時(shí)。
            我們常說的override(覆蓋)就是針對(duì)虛函數(shù)而言。
            對(duì)虛函數(shù)的實(shí)現(xiàn)應(yīng)該說各個(gè)編譯器是不一樣的,大多數(shù)的編譯器是這樣的:
            為每一個(gè)有虛函數(shù)的類增加一個(gè)虛表,這個(gè)虛表是靜態(tài)的,還有一個(gè)虛指針,為每個(gè)類對(duì)象。例如:
            // Your original C++ source code
             class Base {
             public:
               virtual arbitrary_return_type virt0(...arbitrary params...);
               virtual arbitrary_return_type virt1(...arbitrary params...);
               virtual arbitrary_return_type virt2(...arbitrary params...);
               virtual arbitrary_return_type virt3(...arbitrary params...);
               virtual arbitrary_return_type virt4(...arbitrary params...);
               ...
             };
            1 編譯器會(huì)為這個(gè)類的虛函數(shù)添加一個(gè)虛表,類似下面的:
            // Pseudo-code (not C++, not C) for a static table defined within file Base.cpp
             
             // Pretend FunctionPtr is a generic pointer to a generic member function
             // (Remember: this is pseudo-code, not C++ code)
             FunctionPtr Base::__vtable[5] = {
               &Base::virt0, &Base::virt1, &Base::virt2, &Base::virt3, &Base::virt4
             };

            2 然后增加一個(gè)指向虛表的指針為每一個(gè)類對(duì)象,這個(gè)指針是隱藏的
             // Your original C++ source code
             
             class Base {
             public:
               ...
               FunctionPtr* __vptr;  ← supplied by the compiler, hidden from the programmer
               ...
             };
            3 編譯器在構(gòu)造中初始化這個(gè)指針
            Base::Base(...arbitrary params...)
               : __vptr(&Base::__vtable[0])  ← supplied by the compiler, hidden from the programmer
               ...
             {
               ...
             }
            在派生類中,它也會(huì)增加一個(gè)隱藏的虛表,但是它可以overrides基類的虛函數(shù)如:
            // Pseudo-code (not C++, not C) for a static table defined within file Der.cpp
             
             // Pretend FunctionPtr is a generic pointer to a generic member function
             // (Remember: this is pseudo-code, not C++ code)
             FunctionPtr Der::__vtable[5] = {
               &Der::virt0, &Der::virt1, &Der::virt2, &Base::virt3, &Base::virt4
             };    

            最后看看底層是如何調(diào)用的如:                                  
            void mycode(Base* p)
             {
               p->virt3();
             }
            主要三部分:
            1.獲取隱藏的指向虛表的指針,并把它放在 register中如r1;
            2.獲取指針r2=r1+3*4(假定一個(gè)指針有四個(gè)字節(jié)) ,并把它放到register中。
            3 根據(jù)r2的地址調(diào)用函數(shù)。

            所以說,調(diào)用一個(gè)虛函數(shù)至少和非虛函數(shù)差不多.
            在這里我們可以看出一個(gè)虛指針的長度,至少是四個(gè)字節(jié),但是要注意編譯器對(duì)它的具體實(shí)現(xiàn)

            純虛函數(shù)怎樣用,下面的例子可以說明這個(gè)問題。
            象下面的代碼就可以用純虛函數(shù)來實(shí)現(xiàn):
            typedef std::vector<Vehicle*>  VehicleList;
             
             void myCode(VehicleList& v)
             {
               for (VehicleList::iterator p = v.begin(); p != v.end(); ++p) {
                 Vehicle& v = **p;  // just for shorthand
             
                 // generic code that works for any vehicle...
                 ...
             
                 // perform the "foo-bar" operation.
                 // note: the details of the "foo-bar" operation depend
                 // on whether we're working with a car or a truck.
                 if (v is a Car) {
                   // car-specific code that does "foo-bar" on car v
                   ...
                 } else if (v is a Truck) {
                   // truck-specific code that does "foo-bar" on truck v
                   ...
                 } else {
                   // semi-generic code that does "foo-bar" on something else
                   ...
                 }
             
                 // generic code that works for any vehicle...
                 ...
               }
             }
            用純虛函數(shù)實(shí)現(xiàn)如下:
            class Vehicle {
             public:
               // performs the "foo-bar" operation
               virtual void fooBar() = 0;
             };
            typedef std::vector<Vehicle*>  VehicleList;
             
             void myCode(VehicleList& v)
             {
               for (VehicleList::iterator p = v.begin(); p != v.end(); ++p) {
                 Vehicle& v = **p;  // just for shorthand
             
                 // generic code that works for any vehicle...
                 ...
             
                 // perform the "foo-bar" operation.
                 v.fooBar();
             
                 // generic code that works for any vehicle...
                 ...
               }
             }

            也可以用繼承的方法來實(shí)現(xiàn)
            class Car : public Vehicle {
             public:
               virtual void fooBar();
             };
             
             void Car::fooBar()
             {
               // car-specific code that does "foo-bar" on 'this'
               ...  ← this is the code that was in {...} of if (v is a Car)
             }
             
             class Truck : public Vehicle {
             public:
               virtual void fooBar();
             };
             
             void Truck::fooBar()
             {
               // truck-specific code that does "foo-bar" on 'this'
               ...  ← this is the code that was in {...} of if (v is a Truck)
             }
            有純虛函數(shù)的是抽象基類,強(qiáng)迫派生類接受基類的接口并實(shí)現(xiàn),在COM(組件)中比較常見,。

            virtual constructor(虛構(gòu)造)的一個(gè)實(shí)現(xiàn)方法之一:
            class Shape {
             public:
               virtual ~Shape() { }                 // A virtual destructor
               virtual void draw() = 0;             // A pure virtual function
               virtual void move() = 0;
               ...
               virtual Shape* clone()  const = 0;   // Uses the copy constructor
               virtual Shape* create() const = 0;   // Uses the default constructor
             };
             
             class Circle : public Shape {
             public:
               Circle* clone()  const;   // Covariant Return Types; see below
               Circle* create() const;   // Covariant Return Types; see below
               ...
             };
             
             Circle* Circle::clone()  const { return new Circle(*this); }
             Circle* Circle::create() const { return new Circle();      }

            void userCode(Shape& s)
             {
               Shape* s2 = s.clone();
               Shape* s3 = s.create();
               ...
               delete s2;    // You need a virtual destructor here
               delete s3;
             }
            注意在VC6中必須寫成Shape*,VC7就不用改,支持返回類型可以變。

            posted on 2009-06-13 17:38 Benjamin 閱讀(2469) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C/C++

            中文精品99久久国产| 色悠久久久久久久综合网| 91精品国产色综合久久| 久久99国产精品一区二区| 久久综合亚洲色HEZYO国产| 人妻精品久久久久中文字幕69| 99久久成人18免费网站| 亚洲天堂久久久| 99999久久久久久亚洲| 午夜精品久久久久久久无码| 亚洲AV无码成人网站久久精品大| 伊人久久免费视频| 久久久亚洲AV波多野结衣| 青青青青久久精品国产| 99精品久久久久久久婷婷| 久久播电影网| 狠狠色噜噜狠狠狠狠狠色综合久久 | 99久久亚洲综合精品成人| 久久久久久精品免费看SSS| 久久99精品久久久久久9蜜桃| 久久精品国产亚洲AV大全| 伊人久久无码精品中文字幕| 国产成人久久激情91| 色偷偷88888欧美精品久久久 | 亚洲伊人久久成综合人影院 | 欧美亚洲国产精品久久久久| 青青草国产精品久久久久| 99精品久久精品| 久久婷婷人人澡人人爽人人爱| 久久国产精品免费| 久久成人影院精品777| 日韩AV无码久久一区二区| 精品久久久久久久国产潘金莲| 性高湖久久久久久久久AAAAA| 国产一区二区三精品久久久无广告 | 亚洲国产精品人久久| 久久99精品久久久久久久久久| 亚洲欧美成人综合久久久| 看久久久久久a级毛片| 久久午夜羞羞影院免费观看| 久久久久久无码Av成人影院|