2014-04-22 63 views
3

請先看看這個簡單的代碼;複製C中多態的構造函數#

這是我的基類:

public class BaseClass 
{ 
    public BaseClass() 
    { 
    } 

    public BaseClass(BaseClass b) 
    { 
    } 

    public virtual string GetMSG() 
    { 
     return "Base"; 
    } 
} 

,這是得到的一個:

public class DrivenClass : BaseClass 
{ 
    public string MSG { get; set; } 

    public DrivenClass(string msg) 
    { 
     MSG = msg; 
    } 

    public DrivenClass(DrivenClass d) 
    { 
     MSG = d.MSG; 
    } 

    public override string GetMSG() 
    { 
     return MSG; 
    } 
} 

,這是測試:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    public BaseClass B { get; set; } 
    public DrivenClass D { get; set; } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     D = new DrivenClass("Driven"); 
     B = new BaseClass(D); 
     MessageBox.Show("B:" + B.GetMSG() + "\nD:" + D.GetMSG()); 
    } 
} 

現在的問題是應該怎樣我這樣做B = new BaseClass(D);作品如B = new DrivenClass(D);

我在多態中使用這個,我喜歡使用一個副本構造函數而不是不同的驅動元素。

我想要的輸出是這樣的:

Driven 
Driven 

,但現在是這樣的:

Base 
Driven 
+2

我很想知道實際所需的行爲是什麼,或者實際的用例需要什麼。 BaseClass.GetMSG被實現爲返回一個硬編碼的字符串「Base」。 BaseClass的實例不是任何派生類的實例,只會打印「Base」。 –

+0

是@JoeAmenta,我知道,我希望通過拷貝構造函數將基類的驅動類中的每個條目分配給一個基類對象,我不能這樣做。實際上,如果我沒有在覆蓋的函數中調用base.GetMsg(),則絕對不應調用基類的函數。 – user3559869

+0

BaseClass類型的對象本身具有哪些獨特的,特定於實例的行爲?如果這是對您實際使用案例的簡化再現,我認爲它簡化得太多了。如果您有一個BaseClass類型(或其派生類之一)的對象列表,並且您希望使用接受BaseClass實例作爲輸入的BaseClass構造函數創建這些實例的副本,那麼您只能依賴實例成員如BaseClass中所定義的,其中沒有任何內容。 –

回答

1

你可以使用一個重寫的虛擬拷貝方法,而不是一個拷貝構造函數。

public class BaseClass 
{ 
    public BaseClass() 
    { 
    } 

    public virtual BaseClass ShallowCopy() 
    { 
     return new BaseClass(); 
    } 

    public virtual string GetMSG() 
    { 
     return "Base"; 
    } 
} 

public class DrivenClass : BaseClass 
{ 
    public string MSG { get; set; } 

    public DrivenClass(string msg) 
    { 
     MSG = msg; 
    } 

    public override BaseClass ShallowCopy() { 
     return new DrivenClass(this.MSG); 
    } 

    public override string GetMSG() 
    { 
     return MSG; 
    } 
} 

然後調用它像這樣:

D = new DrivenClass("Driven"); 
B = D.ShallowCopy(); 

這工作,因爲調用虛方法總是調用子類中的實際重寫實現,從基類接口來調用時也是如此。

+0

使用克隆怎麼樣? – user3559869

+0

你的意思是'ICloneable'接口? [顯然不是一個好主意](https://stackoverflow.com/questions/699210/why-should-i-implement-icloneable-in-c#699221),因爲它並不表示你的副本是深的還是淺的一。儘管你可以簡單地編寫自己的通用接口。 – magnattic

+0

我同意其他意見,但是:首先反思您的設計,然後在實施之前思考您真正想要實現的目標。首先嚐試複製,你可能會走上錯誤的軌道。 – magnattic

0

發生什麼是正常的,因爲你在這裏創建基類的新實例。所以你永遠不會覆蓋GETMSG方法:

B = new BaseClass(D); 

你想要做的是有相同的公共類:

public BaseClass B { get; set; } 

,並賦予它新的DrivenClass值(d)

B = new DrivenClass(D);