2017-05-08 83 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}"); 
    } 
}