簡體   English   中英

純虛函數與虛函數?

[英]Pure virtual function vs. virtual function?

我正在開發一個具有某些功能的類,我認為可能需要稍后擴展,但現在不能。 如果要擴展類,那么我認為這會使實例化基類毫無意義。

例如,假設我的基類是樹。 一種方法是在樹類中放置樹需要做的所有事情,並將其留在那里。 但是,這個樹在以后的生活中可能對程序的其他方面很有用,所以我考慮過創建一個純虛擬onNodeVisited函數。 然后,派生類可以實現自己的onNodeVisited版本,而不必擔心基類中定義的樹遍歷的細節。

不使用純虛函數並將樹功能和特定於應用程序的功能保存在一個類(virtual onNodeVisited )中是否onNodeVisited 或者,我應該使樹類抽象並為特定於應用程序的部分實現一個子類。

我現在不會這樣做。 稍后你可以為Tree創建一個抽象基類並在那里移動代碼,如果這有意義的話。

繼承這種事物的另一個選擇是要調用的函數指針或函數類型。 重用更容易,因為您不必為每種新情況繼續創建新類。

顯然,這必須根據具體情況來決定,對於樹的例子,似乎關鍵的決定/問題是樹的所有用戶是否需要/想要實現onNodeVisited函數。 如果樹可以同樣地與接口的其他部分一起使用(例如,它支持get_next_child()樣式迭代,或者某些“路徑”查找),那么聽起來樹對於從不打算訪問每個部分的人來說可能是有用的。節點,因此不希望實現onNodeVisited函數。 在這種情況下, onNodeVisited不應該是純虛擬的,現在或永遠。 如果你的設計決定是讓樹的界面如此限制,以至於沒有訪問時類沒用,那么你可能會堅持讓人們通過將它onNodeVisited純虛擬來實現onNodeVisited

我可以看到兩個選擇讓我覺得合情合理。

如果你只是考慮可能最終會變得有用的東西,那么我會選擇YAGNI路線,並將其完全排除,直到或除非你發現它真正需要它。

如果你肯定你真的需要它,只是沒有足夠的寫入把它尚未使用其他代碼,那么它的價值設計到類,即使你不使用它然而。

雖然這對於純虛函數來說聽起來不是一個好的情況。 純虛函數意味着1)包含純虛函數的類不能直接實例化 - 它只能用作基類,2)能夠創建派生類的對象,它們必須提供實現純虛函數。

換句話說,純虛函數表示幾乎與您的情況相反。 必須在類的對象完全存在之前覆蓋純虛函數。 你(最多)建立一個“鈎子”,使特定的未來擴展變得容易。

我會重復我的建議上面:除非你是這使用相當肯定,它可能是最好只在需要什么樣的設計,並留在這一點。 如果決定你需要(或真的,真的希望)包括它,我會盡量保持它作為松耦合合理。 顯而易見的途徑是使用訪問者模式。 這定義了一個處理訪問和處理節點的單獨訪問者類。 樹節點類將包括一個額外的函數(傳統上稱為accept ),它接受一個參數:一個訪問者對象的指針(或引用)。 訪問者類是一個典型的抽象基類,具有用於在節點上進行處理的成員函數(傳統上稱為visit )。 這通常一個抽象基類。

然后,當您決定在每個節點上確實要執行哪些處理時,您將從visitor派生一個新類來覆蓋visit以執行每個節點的處理。 樹根本不需要修改。 這是眾所周知的模式(即使在C ++程序員中,他們對其他人的模式通常不那么“友好”)所以假設你使用普通名稱,大多數人會很快和容易地認出它。 這也有助於代碼本身通常非常簡單 - accept通常看起來像這樣:

struct tree_node;

class visitor { 
    virtual void visit(tree_node *node) = 0;
};

struct tree_node { 
    void accept(visitor *v) { v->visit(this); }

    // ...
};

然后要添加處理,您從訪問者派生,並覆蓋visit以執行您需要的處理。 樹的一面根本不需要修改。 這也很精確,可以編寫單個訪問者類來訪問多種類型的節點(即使節點不通過繼承關聯)。

暫無
暫無

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

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