我們寫了一個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;
}
將上述註釋去掉,增加了虛函數之後便可以編譯通過,但是結果可能還不能如願:
#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;
}