顛覆你對方法呼叫的看法 高!

2021-06-20 13:51:23 字數 2241 閱讀 2405

注意:如果你是乙個初學者,對例項方法,虛方法的呼叫還不太清楚,強烈建議你不要閱讀本文,因為這裡面的**會讓你完全崩潰掉。

如果你對例項方法,虛方法的執行機制已經瞭如指掌,並且,對方法和物件的記憶體布局也心中有數,那麼本文可能會顛覆你以前對他們的認識。

閱讀本文的最佳方式就是親自演練一下,如果看完之後有疑惑,那麼是正常的,但是稍加思考就會想明白。

我說,string變數可以直接引用乙個object物件!

我說,派生型別的變數可以直接引用基型別的物件!

你會說,老兄,別開玩笑了,派生型別怎麼可以指向乙個基型別的物件呢!

我會讓你見證一下奇蹟,並在文章的結尾再給你乙個更加不可思議的例子。

首先,請看下面的**:

class

program

}class

base

}class

derived : base

}

毫無疑問,在執行時一定會丟擲乙個異常,因為base物件無法轉換為derived物件。

但是,現在,我就想讓d指向base物件,並且可以呼叫base中的print方法,該怎麼做呢?

用filedoffset可以做到這一點,但首先需要定義乙個叫做manager的類,裡面包含兩個例項字段,乙個為derived,乙個為base。如下:

[structlayout(layoutkind.explicit)]

class

manager

現在,通過為b和derived都指定了相同的偏移,所以,b和derived都指向了同乙個物件,base物件。

由於derived現在指向了base物件,那麼如果我呼叫d.print方法,呼叫的是base的printf還是derived的print方法,還是丟擲乙個異常。請看如下**:

class

program

}

執行上面**,會輸出什麼呢?

答案是,「in derived」。

這很不可思議,因為derived指向的是base物件,現在呼叫的確實derived的方法。想要了解原因,請看下圖:

這裡,儘管derived指向的是乙個base物件,但是,clr發現print是乙個非虛方法,所以clr並不關心derived變數指向什麼物件,clr根據derived變數的型別來呼叫print方法,這裡derived是乙個derived型別,所以clr會呼叫derived中的print,最終輸出in derived。

第二個例子:

下面的這個例子也很不可思議,同樣會顛覆你傳統的觀點。

讓我們將上面的print方法改為virtual方法,最終如下:

[structlayout(layoutkind.explicit)]

class

manager

class

base

}class

derived : base

}

現在,執行如下測試**:

class

program

}

這次結果會是什麼呢?強烈建議你自己思***。

結果是,in base!

是不是及其不可思議!為了更清楚的理解原因,請看下圖:

這裡,儘管derived指向的是base物件,但是,當clr看到derived.print這行**時,由於print是虛方法,所以clr會檢視derived所指向的base物件。

clr發現base物件裡的type object pointer指向乙個base type object,於是就呼叫base type object中的print方法,所以最終會輸出inbase。

總結:沒有總結可不好。

本質上,子型別是不能引用父型別物件的。但是,我們可以通過fieldoffset繞過這一限制。通過子型別的變數來呼叫父物件的方法,這很是不可思議,但更不思議的是,當子型別的變數指向父物件時,竟然可以呼叫子方法!

那麼上面的本質是什麼呢?當clr呼叫乙個非虛方法時,不會關心變數具體指向的是什麼,因為clr此時是通過變數的型別來呼叫方法。如果方法時虛方法,那麼clr為了實現多型,需要檢視這個變數指向的是什麼物件,然後在通過物件的type object pointer找到對應的type object,然後呼叫type object中的方法。

對方法的驗證

1 把基準資料提出 import pandas as pd dframe1 pd.read excel window regulator分析報告分析.xlsx sheetname sheet1 dframe2 pd.read excel window regulator分析報告分析.xlsx she...

子窗體與父窗體呼叫對方js方法

有時候為了減少乙個頁面內的 量,會將部分內容放到子窗體中,如後台管理中用iframe來進行管理 dviframe src 1 在父窗體獲取子窗體的windows物件 var formwindow dviframe 0 contentwindow 0 是jq物件轉換成dom物件,再獲取子窗體windo...

領導力提公升 你找對方法了嗎?

自製是領導力提公升中領導者面臨的最大的考驗。領導者的一舉一動都會向員工傳達一定的資訊。因此,領導者應該謹慎行事。頌揚 謙遜或憤怒的言辭能夠增強或損毀領導者的影響力。員工會審視領導者的一舉一動。他們是否願意追隨領導者也將受到領導者行為的影響。人們可能會忽視自己的行為及其影響。但是,領導者不能無視自己的...