2017-05-08 66 views
0

我得到一個錯誤:「類型的書」不包含一個構造函數0' 參數」當我嘗試設置我的構造函數如下:c#:繼承和抽象類 - 基礎。 VS:基地(在構造函數初始化)

using System; 
using System.Collections.Generic; 
using System.IO; 
abstract class Book 
{ 

    protected String title; 
    protected String author; 

    public Book(String t,String a){ 
     title=t; 
     author=a; 
    } 
    public abstract void display(); 

} 

class MyBook : Book 
{ 
    private int price = 0; 

    public MyBook(string t, string a, int p) 
    { 
      base.title = t; 
      base.author = a; 
      this.price = p; 
    } 

    public override void display() 
    { 
     Console.WriteLine($"Title: {title}"); 
     Console.WriteLine($"Author: {author}"); 
     Console.WriteLine($"Price: {price}"); 
    } 
} 

我已經將問題縮小到了我使用基本關鍵字的方式。我應該在其構造函數聲明中使用基礎構造函數初始值設定項和base關鍵字。

public MyBook(string t, string a, int p) 
    : base(t, a) 
    { 
      this.price = p; 
    } 

請問有人請向我解釋爲什麼我不能使用base。在我的構造函數中?是否因爲標題和作者變量都是抽象類的受保護成員?我認爲,因爲我是從Book派生的,所以我可以訪問這些受保護的成員。還是因爲我沒有實例化我的子類,因此我不能這樣設置我的構造函數?

+1

因爲你已經定義了一個基礎的構造函數,預計2個參數,纔可以初始化和爲您服務它的成員。 – vendettamit

回答

1

您可以按照您嘗試的方式使用受保護的屬性。這不是你遇到的問題。當您嘗試創建派生類的實例時,程序需要知道要調用的基類的哪個構造函數來創建對象的該部分。如果不指定,則調用默認(無參數)構造函數。基類沒有其中之一,所以你得到錯誤。 :base(t,a)有必要告訴它要使用哪個構造函數,以及通過它的是什麼參數。如果你願意,你可以這樣做:

public MyBook(string t, string a, int p) 
: base(t, a) 
{ 
     base.title = t; 
     base.author = a; 
     this.price = p; 
} 

當然,在這個例子中,這將是愚蠢的,但你可以看到,它會讓你在你嘗試的方式使用這些屬性。

+0

謝謝凱爾!我現在明白了 – xslipstream

0

不能在不調用構造函數的情況下設置基類的屬性。因爲基類有一個構造函數,它接受參數(並且沒有默認構造函數),所以您必須顯式調用基類的構造函數。

public MyBook(string t, string a, int p) 
    :base(t, a) 
{ 
    this.price = p; 
} 

當你創建的派生類的一個實例,你封筆基類的一個實例。如果一個類具有需要參數的構造函數,並且沒有有一個默認的構造函數,那麼創建它的唯一方法就是調用其中一個構造函數。

如果BookMyBook在同一個組件,那麼你可以添加一個protected默認構造函數,只有繼承類可以調用,像這樣:

protected Book() { } 

但最好做到這一點。您將該構造函數放在那裏是有原因的,所以您不希望任何「繞過」該構造函數 - 甚至不需要繼承類。

例如,您可能會決定Book不能有空titleauthor,因此您將驗證放在構造函數中以確保它們不爲null。對於MyBook來說,調用基類構造函數是件好事,因爲現在驗證總是發生。

+0

其實他可以...... ctor的參數只是他錯過的語言限制。 – vendettamit

+0

他可以設置基類的屬性。他不能*設置基類的屬性。 (是的,我可以做得更清楚。) –

+0

嗯,你的_just_讓你解釋它。 :) – vendettamit

1

如果您編寫的類沒有構造函數,編譯器會爲您定義一個無參數的默認構造函數,以方便編寫簡單的快速類。

當您開始明確定義構造函數時,編譯器假定您正在定義您想要的具體構造函數集。這使您可以控制如何創建類,同時保留編寫使用默認構造函數的簡單類的便利性。

MyBookBook。在MyBook可以初始化之前,Book必須首先這樣做。但是這裏沒有無參數的構造函數。 Book已經明確地就編譯器而言選擇了禁止你在這裏做什麼。該語言假定如果你想讓人們 - 子類,你的阿姨Sally,任何人 - 能夠用無參數的構造函數創建一個Book,你應該提供一個。

public MyBook(string t, string a, int p) 
{ 
     base.title = t; 
     base.author = a; 
     this.price = p; 
} 
+0

謝謝你編!我現在明白了 – xslipstream

0

雖然有多種方法可以解決您的問題。我會試着從更好的設計角度回答,而不是解決你的問題。

如果我早點來定義這樣一類結構我會去這樣做這樣

using System; 
using System.Collections.Generic; 
using System.IO; 

abstract class Book 
{ 
    protected String title; 
    protected String author; 

    public Book(String t, String a) 
    { 
     this.title = t; 
     this.author = a; 
    } 

    public abstract void display(); 
} 

class MyBook : Book 
{ 
    private int price = 0; 

    public MyBook(string t, string a, int p) : base(t, a) // Let the base class decide what it wants to do with these arguments 
    { 
     this.price = p; 
    } 

    public override void display() 
    { 
     Console.WriteLine($"Title: {title}"); 
     Console.WriteLine($"Author: {author}"); 
     Console.WriteLine($"Price: {price}"); 
    } 
}