一次实现可以在某些场合替代菱形继承?
????? 前不久在C++板塊請(qǐng)教過這樣一個(gè)問題:“多個(gè)基類中相同的純虛函數(shù),只需在派生類中實(shí)現(xiàn)一次”是否是標(biāo)準(zhǔn)行為。這個(gè)問題直到現(xiàn)在我也還沒能確定,不過我在VC2005、VC2008和g++上都試過,該特性在所有這些編譯器上都可以正常工作,所以應(yīng)該八九不離十了。另外,記得當(dāng)時(shí)星星有“語法正確邏輯說不過去”一說,那時(shí)想想確實(shí)也有些別扭。不過,最近在工作中又遇到了一個(gè)類似的問題,再加上一些突發(fā)奇想,于是產(chǎn)生了標(biāo)題中的這個(gè)想法??紤]下面的三個(gè)類:
? ?
??? ClientOne通過調(diào)用Server的method_one()和method_two()方法和Server交互,ClientTwo通過調(diào)用Server的余下方法與Server交互。通常在設(shè)計(jì)良好的OO項(xiàng)目中,為了降低各對(duì)象之間的依賴,像這種問題都需要提取接口,并根據(jù)客戶對(duì)接口進(jìn)行隔離,那么,上面的依賴關(guān)系就會(huì)變成下面這樣:
? ?
??? 現(xiàn)在Server只要直接實(shí)現(xiàn)InterfaceOne和InterfaceTwo這兩個(gè)接口就行了,接口實(shí)現(xiàn)在C++中表現(xiàn)為繼承,所以在C++中Server直接派生自這兩個(gè)基類就行了。問題似乎解決了。但如果ClientOne和ClientTwo都需要通過另一個(gè)叫做“shared_method()"的方法與Server交互,那會(huì)怎樣?對(duì),繼續(xù)提取接口:
? ?
??? 這里出現(xiàn)了菱形繼承,所以在C++中就需要使用虛繼承,代碼就會(huì)是這樣:
??? class SharedInterface {
??? public:
??????? virtual void shared_method() = 0;
??????? virtual ~SharedInterface() {}
??? };
?????? ?
??? class InterfaceOne : public virtual SharedInterface {
??? public:
??????? virtual void method_one() = 0;
??????? virtual void method_two() = 0;
??????? virtual ~InterfaceOne() {}
??? };
?? ?
??? class InterfaceTwo : public virtual SharedInterface {
??? public:
??????? virtual void method_three() = 0;
??????? virtual void method_four() = 0;
??????? virtual ~InterfaceTwo() {}
??? };
?????? ?
??? class Server : public InterfaceOne, public InterfaceTwo {
??? public:
??????? virtual void method_one();
??????? virtual void method_two();
??????? virtual void method_three();
??????? virtual void method_four();
??????? virtual void shared_method();
??????? ...
??? };????? ?
??? 有些時(shí)候并不是所有人都愿意使用虛繼承,所以某些人就會(huì)突發(fā)奇想,看看自吸磁力泵能否回避之。我就是其中之一。根據(jù)”一次實(shí)現(xiàn)“,我把shared_method下推至InterfaceOne和InterfaceTwo,這樣就可以把SharedInterface去掉:
? ?
??? 哈哈,不但去掉了虛繼承,還直接少了一層繼承,這個(gè)世界干凈啦!當(dāng)然,這個(gè)方法對(duì)于兩個(gè)接口中存在很少部分的重疊方法還是挺方便的,但如果重疊方法過多,還是應(yīng)該提取出一個(gè)公共接口,以避免自吸磁力泵過多的重復(fù)。
評(píng)論列表
周星星2014-4-7 15:44:47
re: “一次實(shí)現(xiàn)”可以在某些場(chǎng)合替代棱形繼承?
從編譯器實(shí)現(xiàn)手段上講,你的這個(gè)做法應(yīng)該是安全的。
"有些時(shí)候并不是所有人都愿意使用虛繼承"
--- 虛繼承挺好的呀!我覺得虛繼承唯一的缺點(diǎn)是 如果不知道當(dāng)時(shí)或以后會(huì)有InterfacdeTwo的話則無法確定InterfacdeOne需不需要虛繼承SharedInterface。
如果接口交叉過多的話,使用虛繼承可能層次變得非常復(fù)雜且難于擴(kuò)充,可以使用另一種解決手段是,
class Server
{
public:
??? void shared_method();
??? void method_one();
??? void method_two();
??? void method_three();
??? void method_four();
};
// InterfaceOne.hpp
class Server;
class InterfaceOne
{
public:
??? void shared_method();
??? void method_one();
??? void method_two();
private:http://www.hrbust.edu.cn/
??? Server* pServer_;
};
// InterfaceOne.hpp
#include "Server.hpp"
void InterfaceOne::shared_method() { pServer_->shared_method(); }
void InterfaceOne::method_one() { pServer_->method_one(); }
void InterfaceOne::method_two() { pServer_->method_two(); }
笨笨豬2014-4-7 15:44:47
re: “一次實(shí)現(xiàn)”可以在某些場(chǎng)合替代棱形繼承?
TO:星星
你的這種思想很好!很多時(shí)候我們的確是在濫用繼承關(guān)系,經(jīng)常在需要使用委托的時(shí)候卻選擇了繼承。不過對(duì)于當(dāng)前這個(gè)問題,我覺得繼承要比委托更恰當(dāng),我想到的有兩方面原因:
1. 因?yàn)槲以谶@里要表達(dá)的是接口與實(shí)現(xiàn)之間的關(guān)系(我所說的接口指的是純抽象類,不包含任何狀態(tài),我們只能通過生成子類的實(shí)例來使用它),而不是其他的什么關(guān)系。
2. 繼承比委托更簡單,雖然委托具有更大的靈活性,但在這里不必要。如果在這個(gè)問題上使用委托,我們就必須再額外多管理兩個(gè)對(duì)象的生命周期,因?yàn)楝F(xiàn)在InterfaceOne和InterfaceTwo變成了具體類,而不是接口,必須要被創(chuàng)建和管理。
我并不是說虛繼承怎么樣不好,而是引入虛繼承之后,就出現(xiàn)了不一致性,我必須要時(shí)刻記住哪里該用常規(guī)繼承,哪里該用虛繼承。
另外,我覺得這個(gè)問題的更本原因是因?yàn)镃++不支持interface關(guān)鍵字造成的。對(duì)于那些有狀態(tài)的基類,菱形繼承中如果不使用虛繼承肯定會(huì)產(chǎn)生二義性,但是對(duì)interface這樣的無狀態(tài)的純抽象基類,菱形繼承中不存在任何二義性
轉(zhuǎn)載于:https://www.cnblogs.com/shhxpump/p/3754729.html
總結(jié)
以上是生活随笔為你收集整理的一次实现可以在某些场合替代菱形继承?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 急救知识收集
- 下一篇: Origami – 用于 Quartz