一些不太常用C++語法

慢慢更新:
1. placement new 方法
如:pi = new (ptr) int; //placement new
    括號裏的參數是一個指針,它指向一個內存緩衝器,new操作將在這個緩衝器上分配一個對象。Placement new的返回值是這個被構造對象的地址(比如扣號中的傳遞參數)。placement new主要適用於:在對時間要求非常高的應用程序中,因爲這些程序分配的時間是確定的;
    STL 標準庫中 allocator 空間分配器, 就使用了這個語法。
先使用 malloc 分配內存p. 然後 在該內存內構造自己的類對象   new(p) T1(value) ; T1 是構造的類型,value 是類型的值

2. naked function
當你的函數內部較簡單,用不到太多寄存器。或者需要根據上下文決定一些寄存器變量的時候。可以用naked 函數。對於一般的函數,如果必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。naked call不產生這樣的代碼。使用naked函數,我們可以自己編寫乾乾淨淨的函數,特別是當你代碼沒有使用這些寄存器的時候。可以像內聯函數一樣,省略一些操作。              
       void __declspec(naked) MyNakedFunction()
        {
            // Naked functions must provide their own prolog.
            __asm
            {
                PUSH EBP
                MOV ESP, EBP
                SUB ESP, __LOCAL_SIZE
            }

            // And we must provide epilog.
            __asm
            {
                POP EBP
                RET
            }
        }

3. 指向類成員函數的指針
在MFC庫中很多窗口基類中調用派生類的消息處理函數。因爲windows消息衆多,如果爲每個消息都設立虛函數,而每個虛函數都佔用4 bytes,那樣很多類體積將非常龐大。而且有些地方基類設計時考慮到派生類在此可能要作些處理,又不想使用虛函數的話也可以使用指向成員函數的指針。如下面的類。如果派生類沒有修改pf成員,在release中  (this->*pf)() 將被優化掉。而且使用指向成員函數的指針也不用定死函數名字.
class animate
{
typedef void (animate::*pfun)();
public:
    animate() {pf=static_cast<pfun>(donothing);}
    void sleep()
    {   
        cout<<"animate sleep"<<endl;
        (this->*pf)();       
    }
    void donothing(){}
pfun pf;
};


class fish:public animate
{
public:
    fish() {pf = static_cast<pfun> (test);}
    void test()
    {
        cout<<"使用基類指針調用派生類非虛函數"<<endl;
    }
};



int _tmain(int argc, _TCHAR* argv[])
{

    animate* fs = new fish;   
    fs->sleep();   
    delete fs;
    return 0;
}

4 __declspec(novtable) 

    C++中沒有提供類似interface這樣的關鍵字來定義接口,但是Mircrosoft c++中提供了__declspec(novtable)來修飾一個類,來表示該類沒有虛函數表,也就是虛函數都(應該)是純虛的
       聲明的基類沒有 vtable(虛擬函數表), 但還是有vptr指針(指向虛擬函數表)的。所以a1* a= new a1; a->hello()執行將會出錯 。 而從a1派生的b1是有vtable的。所以 a1* a = new b1; a->hello() 將調用 b1 的hello函數。如果b1未定義hello函數,那麼將調用 a1 函數。其實還是從b1對象的vptr指向的vtable中索引的函數地址。編譯時由於b1中沒有定義hello虛函數.   vtable 中虛函數hello指向的是a1類hello函數地址。良好的面向對象設計應該由派生類完成實現。面向對象規則第一條就是基於接口編程。所以將a1 函數均定義爲純虛函數,a1相當於接口,由派生類b1來實現,這樣將抽象與實現之間解耦合,更符合面向對象規範。
       這樣定義的類a1不能調用虛函數。所以a1 類應看成接口。不應生成 a1 類對象。同樣程序生成時將節省a1 類 vtable 的空間。如果有大量虛函數,節省空間還是可觀的 函數個數*4. 
     次關鍵字爲vc 所有,其他c++編譯器並不支持
                                                                                                        
class __declspec(novtable) a1
{
public:
    a1() {}
    virtual void hello()
    {
        cout<<"a hello"<<endl;
    }
};

class b1:public a1
{
public :
    b1() {}
    void hello()
    {
        cout<<"b hello"<<endl;
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章