簡體   English   中英

函數指針和虛函數

[英]function pointer and virtual function

我想我的問題應該很愚蠢,但是確實,我從未見過被聲明為虛函數的函數指針。 是否有一個原因?

編輯:

我應該說:它所指向的功能是否有可能被指定為虛函數?

好,是的(也不是)。

普通函數指針不能指向非靜態成員函數。 它們只能指向獨立的函數,這就是為什么對於普通函數指針而言,函數虛擬性問題甚至沒有出現的原因。

為了指向C ++中的成員函數,您需要一種特殊的指針:一種具有指向成員函數類型的指針。 這種類型的指針也可以指向非虛擬成員函數和虛擬成員函數。 如果要指向虛擬成員函數,則無需采取特殊步驟。 例如

struct B { 
  virtual void foo() {} 
  void bar() {} 
};

...
B b;
void (B::*pfunc)(); // declare a pointer to a member function

pfunc = &B::foo; // make it point to `B::foo`
(b.*pfunc)(); // calls `B::foo` for object `b`

pfunc = &B::bar; // make it point to `B::bar`
(b.*pfunc)(); // calls `B::bar` for object `b`

但是,當您使此類指針指向虛擬成員函數時,必須記住,它實際上並沒有綁定到類層次結構中該函數的特定版本。 有關要調用的特定功能的決定是在調用時做出的。 例如

// given the above `B`
struct D : B { 
  virtual void foo() {} 
};

...
void (B::*pfoo)(); // declare a pointer to a member function
pfoo = &B::foo; // and make it point to `B::foo`

在上面的示例中,我們確定了指針pfoo指向B::foo 還是我們? 實際上,指針並非專門鏈接到B::foo 這兩個電話

B b;
D d;

(b.*pfoo)();
(d.*pfoo)();

將調用兩個不同的函數。 第一個將為對象b調用B::foo ,而第二個將為對象d調用D::foo ,即使我們在兩種情況下都使用了相同的指針值。 實際上,在許多應用程序中這是有道理的。

但是,在某些低級情況下,將指針綁定到特定版本的虛擬函數將很有用。 也就是說,當我們執行操作時,有一個指針可以對對象d B子對象調用B::foo

(d.*pfoo)();

為了實現這一點,我們需要能夠指定是要早期綁定(在初始化時)還是在后期綁定(在調用時)。 不幸的是,C ++語言沒有提供這種功能。

函數指針只是指向函數的指針。 就像存儲type任何指針一樣,它只存儲函數的地址。

關鍵字virtual用於通過動態調度實現多態行為(在基類和派生類的函數之間)。

鑒於以上兩個截然不同,將函數指針虛擬化的想法根本沒有意義。

它指向的功能是否指定為virtual?
正如我之前提到的,函數指針僅存儲函數的地址。 這只是一種type 例如:

int *i = NULL;
void doSomething();
typedef void(*ptr)() = NULL;
ptr = &doSomething();

在上面的示例中:
iint * 同樣,
ptr是可以存儲不帶參數且不返回參數的函數地址的類型。

因此,是的,從根本上講,您可以將函數指針指向的函數設置為虛函數,就像通過在類中將特定函數聲明為虛函數來使任何函數變為虛函數一樣。

作為類型的函數指針可以指向具有該原型的任何函數,同時將函數聲明為虛擬的,意味着對特定函數啟用了動態分派,就像您看到的一樣。

虛擬性是成員函數的屬性。 如果您有一個指向虛擬成員函數的指針,則將自動進行虛擬調用。 常規函數不能是虛函數,因此虛函數指針毫無意義。 在任何一種情況下,將函數指針虛擬化都是沒有意義的,因為指向它的函數很重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM