这句话在很多文章中出现过 析构函数不能被继承这个我知道 但是基类的构造函数也没有被继承吗??
class A
{
public A()
{
Console.WriteLine("I am A");
}
}
class B : A { }
class Program
{
static void Main(string[] args)
{
B b = new B();
//I am A
}
}
可是上面一段代码 基类的构造函数确实被调用了
难道被调用了就不算继承吗 这里我很是不明白哦 请教大虾们(惭愧啊。。)
13 个解决方案
#1
默认构造器是被继承了.
#2
实力化子类时时首先构建它的基类,如果在派生类的构造函数没有初始化基类的构造,那么调用基类的无参数的构造函数。因此看起来像是继承了.
#3
默认构造函数会被自动调用,但是我觉得不叫继承。如果不加入有参数的构造i函数,每个类都有默认的构造函数,不能说是从父类继承的。
继承的函数,你只是可以使用,并不会被自动调用。
如果你在子类里定义同样的名字和参数的函数。vs会提示你要覆盖(使用new关键字),覆盖后要调用父类的函数。要使用base.Function()这样的形式吧。
继承的函数,你只是可以使用,并不会被自动调用。
如果你在子类里定义同样的名字和参数的函数。vs会提示你要覆盖(使用new关键字),覆盖后要调用父类的函数。要使用base.Function()这样的形式吧。
#4
那再看个例子
class A
{
private int m = 5;
public int Add()
{
return ++m;
}
}
class B : A
{
}
class Program
{
static void Main(string[] args)
{
B b = new B();
int a = b.Add(); //a=6
}
}
基类中有个私有成员变量 当然了 在派生类中是无法访问的 但是调用继承过来的Add方法 可以让其加1
那我就要问问这个私有成员变量了
首先我先认为这个基类中的私有成员变量在派生类中是被继承过来的,只不过不能访问 调用被继承过来的Add方法 所以返回加1
那我假如这个基类中的私有成员变量在派生类中并没有被继承 只不过调用了base.m内部操作 当然这样写肯定是错的 私有嘛 外部类是访问不了的 我就是打个比喻
就是因为访问不了 所以不知道是否这个私有变量是不是被继承过来的 还是内部通过什么方法去调用基类中的私有变量
擦 不知道说明白了没。。 牛角尖?
#5
继承跟对消(重写)是一对概念,换句话说就是:并不假设子类会调用父类方法。
#6
我想,你不要以为B类对象实例内部有什么组合的另外一个A类对象实例。那种错误的概念很可能来自于10几年前的某一两本流行的c++教程,那种教程中容易按照某个公司的早期c++的实现机制来套用成OOAD概念,是一种错误的解释。
OOP有至少30年的历史,从很早的smalltalk等语言到现在,基本上都比上述的那个c++编译器要更加准确地实现了OOAD机制。假设B类型继承自A类型,那么它只是定义时分为两个类型对象,但是类型实例对象则是一个。也就是说某个B类的对象实例x,它自身同时也就是一个A类型的对象实例,混句话说x的内存数据部分就是自己的内存数据部分,m变量本来就在x内部私有,只不过调用A类的方法时可以访问到x自己的私有m,调用B类的方法是无法直接访问到自己的私有m(因为编译器不知道私有数据m在B类对象实例的数据部分中的“偏移地址”)。
一个B类对象x“就是”一个A类对象x。继承不是说一个B类对象内部还有一个什么指针指向另外一个私有A类对象作为自己的base对象。base这个语法是指调用父类声明的方法,不是指调用父类对象。
#7
OOAD强于OOP,而不是总是用某种编译器的底层概念套用成OO概念。
如果某个编程语言偏离了只要的面向对象原则,我们应该首先考虑扔掉这个编程语言,而不是面向对象设计原则。不管是对c#还是对c++,都是如此。
而面向对象中,继承和重写是很简单的概念,没有OOP那么复杂。继承是指两个类型的定义,但是对象个体只有一个。比如说一个“人x”她既是一个女人、又是一个母亲、又是一个寡妇、又是一个年轻寡妇、又是一个vip、又是一个驾驶员、又是一个患者、又是一个器官捐助人、又是一个员工,又是一个正式员工、又是一个老员工、又是一个女员工、又是一个有生产效率的员工........总之都是一个人。不要以为一个人身体里为每一个父类(以及祖先类)而长出了另外一个人来,那就是见了鬼了(那样你就把面向对象想得太繁琐和低级了)。
如果某个编程语言偏离了只要的面向对象原则,我们应该首先考虑扔掉这个编程语言,而不是面向对象设计原则。不管是对c#还是对c++,都是如此。
而面向对象中,继承和重写是很简单的概念,没有OOP那么复杂。继承是指两个类型的定义,但是对象个体只有一个。比如说一个“人x”她既是一个女人、又是一个母亲、又是一个寡妇、又是一个年轻寡妇、又是一个vip、又是一个驾驶员、又是一个患者、又是一个器官捐助人、又是一个员工,又是一个正式员工、又是一个老员工、又是一个女员工、又是一个有生产效率的员工........总之都是一个人。不要以为一个人身体里为每一个父类(以及祖先类)而长出了另外一个人来,那就是见了鬼了(那样你就把面向对象想得太繁琐和低级了)。
#8
恩 base调用的父类所指向方法列表Loader Heap上的地址 对吧 稍微开始明白些了 让我在琢磨下 头脑乱的很
#9
数据m虽然在A类中定义,但是这只是在类型内定义。在对象内,虽然这个对象是以B类型实例化的,它自己的数据段也包括m,只不过只有使用来自于A类得方法才能访问自己的m。
#10
吃个饭先。。 饭后消化。。 马上来
#11
假设在A类上有构造方法 public A(int x){} 于是B类不用声明也就可以这样实例化,那么这就是继承。但是c#完全不支持构造方法继承。不过对于没有参数的构造方法,它保持跟c++的兼容,所以自动调用了base定义的没有参数的构造方法。这显然不是OOAD概念,是某个编译器的概念。
比如说你写代码
那么c#编译器在生成.net平台的程序(你可以看作是msil)时,默认地会额外自动生成B类型的实例化方法(可见不能继承),而且此方法中只有一条方法就是调用A类型中的实例化方法。可见B类型上这个简写的实例化方法,并不是.net的特性,纯粹是c#语法糖。
比如说你写代码
public class A
{
private int m;
public A()
{
m = 9;
}
protected int M
{
get
{
return m;
}
set
{
m = value;
}
}
}
public class B : A { }
A x = new B();
Console.ReadKey();
那么c#编译器在生成.net平台的程序(你可以看作是msil)时,默认地会额外自动生成B类型的实例化方法(可见不能继承),而且此方法中只有一条方法就是调用A类型中的实例化方法。可见B类型上这个简写的实例化方法,并不是.net的特性,纯粹是c#语法糖。
#12
差不多明白了
过1,2个小时结贴哈 谢谢
过1,2个小时结贴哈 谢谢
#13
public class A
{
public A(int i)
{
}
}
public class B:A
{
public B(int i):base(i)
{
}
}
#1
默认构造器是被继承了.
#2
实力化子类时时首先构建它的基类,如果在派生类的构造函数没有初始化基类的构造,那么调用基类的无参数的构造函数。因此看起来像是继承了.
#3
默认构造函数会被自动调用,但是我觉得不叫继承。如果不加入有参数的构造i函数,每个类都有默认的构造函数,不能说是从父类继承的。
继承的函数,你只是可以使用,并不会被自动调用。
如果你在子类里定义同样的名字和参数的函数。vs会提示你要覆盖(使用new关键字),覆盖后要调用父类的函数。要使用base.Function()这样的形式吧。
继承的函数,你只是可以使用,并不会被自动调用。
如果你在子类里定义同样的名字和参数的函数。vs会提示你要覆盖(使用new关键字),覆盖后要调用父类的函数。要使用base.Function()这样的形式吧。
#4
那再看个例子
class A
{
private int m = 5;
public int Add()
{
return ++m;
}
}
class B : A
{
}
class Program
{
static void Main(string[] args)
{
B b = new B();
int a = b.Add(); //a=6
}
}
基类中有个私有成员变量 当然了 在派生类中是无法访问的 但是调用继承过来的Add方法 可以让其加1
那我就要问问这个私有成员变量了
首先我先认为这个基类中的私有成员变量在派生类中是被继承过来的,只不过不能访问 调用被继承过来的Add方法 所以返回加1
那我假如这个基类中的私有成员变量在派生类中并没有被继承 只不过调用了base.m内部操作 当然这样写肯定是错的 私有嘛 外部类是访问不了的 我就是打个比喻
就是因为访问不了 所以不知道是否这个私有变量是不是被继承过来的 还是内部通过什么方法去调用基类中的私有变量
擦 不知道说明白了没。。 牛角尖?
#5
继承跟对消(重写)是一对概念,换句话说就是:并不假设子类会调用父类方法。
#6
我想,你不要以为B类对象实例内部有什么组合的另外一个A类对象实例。那种错误的概念很可能来自于10几年前的某一两本流行的c++教程,那种教程中容易按照某个公司的早期c++的实现机制来套用成OOAD概念,是一种错误的解释。
OOP有至少30年的历史,从很早的smalltalk等语言到现在,基本上都比上述的那个c++编译器要更加准确地实现了OOAD机制。假设B类型继承自A类型,那么它只是定义时分为两个类型对象,但是类型实例对象则是一个。也就是说某个B类的对象实例x,它自身同时也就是一个A类型的对象实例,混句话说x的内存数据部分就是自己的内存数据部分,m变量本来就在x内部私有,只不过调用A类的方法时可以访问到x自己的私有m,调用B类的方法是无法直接访问到自己的私有m(因为编译器不知道私有数据m在B类对象实例的数据部分中的“偏移地址”)。
一个B类对象x“就是”一个A类对象x。继承不是说一个B类对象内部还有一个什么指针指向另外一个私有A类对象作为自己的base对象。base这个语法是指调用父类声明的方法,不是指调用父类对象。
#7
OOAD强于OOP,而不是总是用某种编译器的底层概念套用成OO概念。
如果某个编程语言偏离了只要的面向对象原则,我们应该首先考虑扔掉这个编程语言,而不是面向对象设计原则。不管是对c#还是对c++,都是如此。
而面向对象中,继承和重写是很简单的概念,没有OOP那么复杂。继承是指两个类型的定义,但是对象个体只有一个。比如说一个“人x”她既是一个女人、又是一个母亲、又是一个寡妇、又是一个年轻寡妇、又是一个vip、又是一个驾驶员、又是一个患者、又是一个器官捐助人、又是一个员工,又是一个正式员工、又是一个老员工、又是一个女员工、又是一个有生产效率的员工........总之都是一个人。不要以为一个人身体里为每一个父类(以及祖先类)而长出了另外一个人来,那就是见了鬼了(那样你就把面向对象想得太繁琐和低级了)。
如果某个编程语言偏离了只要的面向对象原则,我们应该首先考虑扔掉这个编程语言,而不是面向对象设计原则。不管是对c#还是对c++,都是如此。
而面向对象中,继承和重写是很简单的概念,没有OOP那么复杂。继承是指两个类型的定义,但是对象个体只有一个。比如说一个“人x”她既是一个女人、又是一个母亲、又是一个寡妇、又是一个年轻寡妇、又是一个vip、又是一个驾驶员、又是一个患者、又是一个器官捐助人、又是一个员工,又是一个正式员工、又是一个老员工、又是一个女员工、又是一个有生产效率的员工........总之都是一个人。不要以为一个人身体里为每一个父类(以及祖先类)而长出了另外一个人来,那就是见了鬼了(那样你就把面向对象想得太繁琐和低级了)。
#8
恩 base调用的父类所指向方法列表Loader Heap上的地址 对吧 稍微开始明白些了 让我在琢磨下 头脑乱的很
#9
数据m虽然在A类中定义,但是这只是在类型内定义。在对象内,虽然这个对象是以B类型实例化的,它自己的数据段也包括m,只不过只有使用来自于A类得方法才能访问自己的m。
#10
吃个饭先。。 饭后消化。。 马上来
#11
假设在A类上有构造方法 public A(int x){} 于是B类不用声明也就可以这样实例化,那么这就是继承。但是c#完全不支持构造方法继承。不过对于没有参数的构造方法,它保持跟c++的兼容,所以自动调用了base定义的没有参数的构造方法。这显然不是OOAD概念,是某个编译器的概念。
比如说你写代码
那么c#编译器在生成.net平台的程序(你可以看作是msil)时,默认地会额外自动生成B类型的实例化方法(可见不能继承),而且此方法中只有一条方法就是调用A类型中的实例化方法。可见B类型上这个简写的实例化方法,并不是.net的特性,纯粹是c#语法糖。
比如说你写代码
public class A
{
private int m;
public A()
{
m = 9;
}
protected int M
{
get
{
return m;
}
set
{
m = value;
}
}
}
public class B : A { }
A x = new B();
Console.ReadKey();
那么c#编译器在生成.net平台的程序(你可以看作是msil)时,默认地会额外自动生成B类型的实例化方法(可见不能继承),而且此方法中只有一条方法就是调用A类型中的实例化方法。可见B类型上这个简写的实例化方法,并不是.net的特性,纯粹是c#语法糖。
#12
差不多明白了
过1,2个小时结贴哈 谢谢
过1,2个小时结贴哈 谢谢
#13
public class A
{
public A(int i)
{
}
}
public class B:A
{
public B(int i):base(i)
{
}
}