如果派生类继承了基类的私有成员,那么为什么不是构造函数呢?

时间:2013-02-25 07:53:20

标签: c# oop inheritance constructor

我想在c#中清楚理解这个基本的OOPS概念。在大多数互联网网站上,我读到派生类继承基类的私有成员,但无法访问这些成员。

  

派生类可以访问public,protected,internal和   受保护的基类内部成员。即使是派生的   class继承了基类的私有成员,它无法访问   那些成员。但是,所有这些私人成员仍然存在   派生类,可以做他们在基地做的同样的工作   阶级本身。例如,假设一个受保护的基类方法   访问私人领域。该字段必须存在于派生中   class,以便继承的基类方法正常工作。

来源:http://msdn.microsoft.com/en-us/library/ms173149.aspx

我的问题是,如果我们认为上面的内容是正确的,那么我们可以说“基类的构造函数是在派生类中继承的,但是派生类只能使用base关键字通过自己的构造函数访问/调用它在创建派生类“

的实例时,构造函数将不可用于外部世界
public class Employee
{
    public int salary;

    public Employee(int annualSalary)
    {
        salary = annualSalary;
    }
}

public class Manager : Employee
{
    public Manager(int annualSalary)
        : base(annualSalary)
    {
        //Add further instructions here.
    }
}

因为要调用基类构造函数,它应该在内部该类中。也许我的解释是错误的。有人可以解释一下吗?

提前致谢!

4 个答案:

答案 0 :(得分:1)

为了构造一个Manager,你需要在基类中使用任何构造函数来构造基类,如果只有一个(如本例所示)你需要调用它。这并不意味着你必须定义一个具有相同签名的构造函数。

你也可以这样做:

public Manager() : base(100000)
{
}

public Manager(string name, int salary) : base (salary)
{
     // store name
}

在构建Manager期间,您将在堆上分配一个新对象。此对象将声明足够的内存,以便它可以存储在基类(Employee)和具体类(Manager)中定义的变量。

答案 1 :(得分:1)

这取决于你如何定义“现在”。如果将其定义为“某处可用”,则基类中的私有成员“存在”以及构造函数。如果将“present”定义为“在该特定类中找到”,则两者都不是“存在”。

尝试使用反射。您将找不到基类的任何私有成员。私有成员是继承的,因此可用,但仍然只在基类中。

构造函数也是如此。

    class A
    {
        private A(int i) { }
        public A() { }
        private void Foo() { }
        public void Bar() { }
    }

    class B : A
    {

    }

    var aProperties = typeof(A).GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy);
    // you won't see Foo in this line, nor any constructors of A
    var bProperties = typeof(B).GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public  | BindingFlags.FlattenHierarchy);

最后,您可以说:

  • 基类的所有成员都以某种方式可用于执行。
  • 没有语法可以从继承类(也不是来自类外的任何地方)调用私有成员
  • 只能使用base关键字从构造函数中调用基类的构造函数。 (构造函数始终从层次结构中的每个基类调用。如果未指定,则它是默认构造函数。)
  • 只有被类声明(或覆盖)的成员实际上才能找到该特定类的“内部”。使用反射,您可以使用BindingFlags.FlattenHierarchy展平基类中的可见成员。私有成员和构造函数只能在声明类中找到。

答案 2 :(得分:0)

  

“基类的构造函数在派生类中继承,但是   派生类只能通过自己的构造函数访问/调用它   使用base关键字,此构造函数将不可用   外部世界在创建派生类的实例时。“

是的,这是正确的。

  

因为要调用基类构造函数,它应该存在于内部   那个班。

就像基地的私人或受保护成员一样,它“存在”,但不能访问外部。

答案 3 :(得分:0)

如果有一种方法可以指定类对于每个父类构造函数,系统应该推断出存在具有相同签名和访问权限的子类构造函数,除了进程字段之外什么也没有用初始化器和链到相应的基础构造函数。通过特定请求提供此类功能不太可能导致错误;当派生类没有指定任何构造函数(而不是仅推断链接到基本无参数构造函数的无参数构造函数)时,如果这是语言设计功能(添加这样的特性),那么即使是推理也是非常安全的然而,对于现有框架来说,这是一个坏主意,因为派生类的作者想要公开无参数构造函数而不是任何参数化构造函数可能没有包含任何构造函数,期望编译器只推断无参数构造函数)。

但是,如果派生类具有自己的任何非平凡构造函数,则子类可能不打算在不经过其中一个的情况下创建任何对象。假设父类只有一个参数化的构造函数,并且有人写道:

class Child : Parent
{
   Thing blah;
   Child()
   {
      blah = new Thing();
   }
}

创建的每个Child都会将blah设置为新内容。现在假设新版本的基类添加了Name属性,并添加了一个指定名称的构造函数。如果构造函数是自动继承的,那么表示myChild = new Child("Fred");的代码将链接到Parent的构造函数,但从未将blah设置为新的Thing

如果一个类可以通过链接到父构造函数然后执行指定的代码块来建立子类不变量,则可以指定每个实例应该生成安全构造函数“继承”。然而,这样的功能实现起来有点复杂,并且不清楚这是否值得花费。