vtable什麼時候會被創建?

我們寫了一個base類,並有(很多)derived類繼承它,同時每個類都有很多成員函數,但是如果類中是沒有虛函數的,那麼編譯器是不會浪費空間去創建vtable的。
看如下代碼:

#include <iostream>

class Window
{
public:
    //virtual void blink() {
    //}
protected:
private:
};

class SpecWindow : public Window
{
public:
    void blink() {
        std::cout << "blinking..." << std::endl;
    }
protected:
private:
};

int main()
{
    Window *aw = new Window;
    SpecWindow *sw = dynamic_cast<SpecWindow*>(aw); // 此句編譯報錯
    dynamic_cast<SpecWindow*>(aw)->blink();         // 此句編譯報錯

    return 0;
}
ellipse
圖1 沒有virtual函數則沒有vtable

將上述註釋去掉,增加了虛函數之後便可以編譯通過,但是結果可能還不能如願:

#include <iostream>

class Window
{
public:
    virtual void blink() {
    }
protected:
private:
    int m_val;
};

class SpecWindow : public Window
{
public:
    void blink() {
        std::cout << "blinking..." << std::endl;
    }
protected:
private:
};

int main()
{
    Window *aw = new Window; // 注意這裏
    if(SpecWindow *spw = dynamic_cast<SpecWindow*>(aw))
    {
        // 不會進入if語句塊
        spw->blink();
    }
    SpecWindow* sw = dynamic_cast<SpecWindow*>(aw);
    if (nullptr != sw)
    {
    	// 不會進入if語句塊
        std::cout << "Convert successful." << std::endl;
    }

    return 0;
}

再進行修改,便可符合預期:

#include <iostream>

class Window
{
public:
    virtual void blink() {
    }
protected:
private:
    int m_val;
};

class SpecWindow : public Window
{
public:
    void blink() {
        std::cout << "blinking..." << std::endl;
    }
protected:
private:
};

int main()
{
    Window *aw = new SpecWindow;
    if(SpecWindow *spw = dynamic_cast<SpecWindow*>(aw))
    {
       	// 成功轉換,並進入if語句塊
        spw->blink();
    }
    SpecWindow* sw = dynamic_cast<SpecWindow*>(aw);
    if (nullptr != sw)
    {
	    // 成功轉換,並進入if語句塊
        std::cout << "Convert successful." << std::endl;
    }

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