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

我希望在c#中清楚地理解这个基本的OOPS概念 . 在大多数互联网站点上,我读到了一个派生类 inherits 基类的私有成员,但它是 cannot access 那些成员 .

派生类可以访问基类的public,protected,internal和protected内部成员 . 即使派生类继承了基类的私有成员,它也无法访问这些成员 . 但是,所有这些私有成员仍然存在于派生类中,并且可以执行与基类本身相同的工作 . 例如,假设受保护的基类方法访问私有字段 . 该字段必须存在于派生类中,以便继承的基类方法正常工作 .

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

我的问题是,如果我们认为上面的内容是正确的,那么我们可以说 "Constructors of base class are inherited in derived class, but derived class can only access/call it through its own constructor using base keyword and this constructor will not be available to outside world while creating instance of derived class" .

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.
    }
}

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

提前致谢!

回答(4)

2 years ago

这取决于你如何定义“现在” . 如果将其定义为“某处可用”,则基类中的私有成员“存在”以及构造函数 . 如果将“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 关键字从构造函数中调用基类的构造函数 . (始终从层次结构中的每个基类调用构造函数 . 如果未指定,则它是默认构造函数 . )

  • 只有一个类声明(或覆盖)的成员实际上找到"inside"该特定类 . 使用反射,您可以使用 BindingFlags.FlattenHierarchy 来展平基类中的可见成员 . 私有成员和构造函数只能在声明类中找到 .

2 years ago

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

你也可以这样做:

public Manager() : base(100000)
{
}

要么

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

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

2 years ago

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

是的,这是正确的 .

因为要调用基类构造函数,它应该存在于该类中 .

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

2 years ago

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

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

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

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

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