2

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

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

来源: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

4 回答 4

1

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

您也可以这样做:

public Manager() : base(100000)
{
}

或者

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

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

于 2013-02-25T08:00:23.923 回答
1

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

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

构造函数也是如此。

    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用来展平基类中的可见成员。私有成员和构造函数只能在声明类中找到。
于 2013-02-25T08:01:15.690 回答
0

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

是的,这是正确的。

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

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

于 2013-02-25T08:37:47.063 回答
0

如果有一种方法可以让类可以指定对于每个父类构造函数,系统应该推断出具有相同签名和访问权限的子类构造函数的存在,它只会处理字段初始值设定项和链,这将很有帮助到相应的基本构造函数。根据特定要求提供此类功能不太可能导致错误;如果派生类没有指定任何构造函数(而不是仅推断链接到基本无参数构造函数的无参数构造函数),即使这是推理,如果这是语言设计特性(添加这样的特性然而,对于现有框架来说,这将是一个坏主意,

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

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

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

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

于 2013-10-31T19:32:19.137 回答