什么时候派生类构造函数被强制使用base关键字?

时间:2016-07-19 14:35:22

标签: c# constructor

  约瑟夫·阿尔巴哈里和本·阿尔巴哈里(奥莱利)在果壳中的C#6.0。

     

版权所有2016 Joseph Albahari和Ben Albahari,978-1-491-92706-9。

在引入隐式调用无参数基类构造函数之后,在第96页说明如下:

  

如果基类没有可访问的无参数构造函数,则子类被强制在其构造函数中使用base关键字。

我正在尝试创建一个代码段来证实这一点,但还没有成功。

我的片段:

public class X
{
    public int Num { get; set; }

    public void Method_1()
    {
        Console.WriteLine("X");
    }

    public virtual void Method_2()
    {
        Console.WriteLine(Num);
    }
}

public class Y : X
{
    public Y()
    {
        Num = 1000;
    }
}

private static void Main(string[] args)
{
    new Y().Method_2();
}

我希望在书肯定之后得到编译器错误,但我没有得到。代码运行并正确打印1000。

我的问题是:本书对于子类被强制使用基本关键字意味着什么?我正在尝试重现这种情况。

我错过了什么?

3 个答案:

答案 0 :(得分:10)

Y 可以访问基类X的无参数构造函数,因为如果类没有定义构造函数,则存在隐式无参数构造函数。< / p>

如果你写:

public class X
{
    public X(int i){}
}

然后X中将不再有Y的无辅助参数构造函数。

答案 1 :(得分:5)

问题源于您对示例代码的误解。因为你没有在class X中定义任何构造函数,所以C#为你定义了一个隐含的构造函数。这个隐式构造函数是一个无参数的构造函数。

您提到的引用是指您实际编写非默认构造函数的情况。

编写非默认构造函数会抑制隐式构造函数的生成。这意味着您必须使用Dervived关键字从base类的构造函数显式调用另一个构造函数

 class BaseClass
 {
     public BaseClass(int i) {}
 }

 class Derived : BaseClass
 {
     public Derived() : base(44) { }
 }

答案 2 :(得分:0)

规则相同,但......

这实际上与访问基类的任何其他成员的常规规则没有什么不同。

构造函数只不过是常规函数。

关键区别在于派生类会自动尝试调用基础构造函数。特别是没有参数的基础构造函数。

如果不存在构造函数,则会出现错误。如果它存在,但您没有&#34;权限&#34;要访问它,就会出错。

如果你没有为基类指定任何构造函数,则假定该类具有无参数的构造函数。

换句话说,如果你没有指定一个构造函数,那么就是为你隐式创建的。

以下是7个您何时会遇到此问题的例子:

示例3 - 确定 - 隐含的默认空构造函数

    class Base
    {
        // No constructor explicitly defined so a default constructor is assumed
        // Having no constructor at all is like having an empty constructor
        // Like this: Base() { }
    }

    class Derived : Base
    {
        // OK - Explicitly calling accessible base constructor
        public Derived() { }
    }

示例2 - 确定 - 可访问的基础构造函数

    class Base {
        // "public" so it's accessible by derived class
        public Base() { } // no parameters - aka parameterless
    }

    class Derived : Base {
        // OK - implicitly calls accessible parameterless constructor base()
        public Derived() {}
    }

示例3 - 确定 - 受保护的方式仍可访问

    class Base {
        // "protected" so it's accessible by derived class
        protected Base() { } // no parameters - aka parameterless
    }

    class Derived : Base {
        // OK - implicitly calls accessible parameterless constructor base()
        public Derived() {}
    }

示例4 - 失败 - 私人无法访问

    class Base {
        // "private" so it's NOT accessible by derived class
        private Base() { } // no parameters - aka parameterless
    }

    class Derived : Base {
        // FAIL - tries to implicitly call parameterless constructor base()
        // ERROR CS0122 - Base.Base() is inaccessible due to it's protection level
        public Derived() { } 
    }

示例5 - 失败 - 始终尝试调用无参数构造函数

    class Base {
        // "private" so it's NOT accessible by derived class
        private Base() { } // no parameters - aka parameterless

        // "protected" so it's accessible by derived class
        protected Base(int a) { } // has parameter - aka NOT parameterless
    }

    class Derived : Base {
        // FAIL - STILL tries to implicitly call parameterless constructor base()
        // ERROR CS0122 - Base.Base() is inaccessible due to it's protection level
        public Derived() { } 
    }

示例6 - 失败 - 除非它不存在,否则假设调用另一个

    class Base
    {
        // notice there is not parameterless constructor 
        // just one constructor does does have parameters

        // "protected" so it's accessible by derived class
        protected Base(int a) { } // has parameter - aka NOT parameterless
    }

    class Derived : Base
    {
        // FAIL - STILL tries to implicitly call parameterless constructor base() which doesn't exist
        // ERROR CS7036 - There is no argument given that corresponds to the required formal parameter 'a' of Base.Base(int)
        public Derived() { }
    }

示例7 - 确定 - 除非您自己打电话

    class Base
    {
        // "private" so it's NOT accessible by derived class
        private Base() { } // no parameters - aka parameterless

        // "protected" so it's accessible by derived class
        protected Base(int a) { } // has parameter - aka NOT parameterless
    }

    class Derived : Base
    {
        // OK - Explicitly calling accessible base constructor with `int` parameter
        public Derived() 
            : base(10) 
            { }
    }