子类通过base等关键字调用父类的成员函数

时间:2022-09-29 16:10:08
在调用父类成员函数时,被调用的成员函数是在父类的变量参数环境下执行(跳转到父类执行),还是在子类的变量参数环境下执行(把父类函数拷贝到子类中执行)?

18 个解决方案

#1


继承后的对象是一个有机的整体。
好比亚洲象是大象的一种,不是说每只亚洲象的肚子里藏着一只大象。

#2


如果要是派生类自己还有一套“环境参数”,那它还要继承基类干嘛。

#3


成员函数也不过是个函数

这跟写成public static形式的函数有什么区别吗

函数的参数是你自己传进去的啊

除非函数代码里还用到了外部变量

#4


真的是你们说的那样吗?
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show();
        }
    }

    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a);
        }
    }
    class A : T
    {
        public new int a = 2;
        public int b = 3;
        public new void show()
        {
            Console.WriteLine("{0} {1}", a, b);
            base.show();
        }
    }
子类通过base等关键字调用父类的成员函数

#5


引用 4 楼 xuzuning 的回复:
真的是你们说的那样吗?


不矛盾
你这个父类函数里用到了父类的成员变量,这个变量对于这个函数来说是个外部变量

#6


引用 楼主 jiang_198901 的回复:
还是在子类的变量参数环境下执行(把父类函数拷贝到子类中执行)?


可以这样理解。方法(以及属性、事件等等所有可继承的东西)可以看作是“按表格查找地址”的,方法代码其实并不属于任何具体的对象。

按照基本的操作系统原理,进程的数据区域跟代码区域其实是分离的。

只不过在代码被call(调用)时.net环境为它实现好了 this 关键字的引用,从而你在方法里的所有关于“当前对象”的引用都动态设置好了。这个this应该就是你所谓的“子类环境”。而实际的实现机制其实异常简单,就是由CLR设置好 this 就行了,并不会低效率地真去“拷贝”一大堆东西。

#7


那么类继承时,类的成员属性不会被覆盖吗?
为何 C# 与其他面向对象的语言不一样呢?

引用 5 楼 Z65443344 的回复:
Quote: 引用 4 楼 xuzuning 的回复:

真的是你们说的那样吗?


不矛盾
你这个父类函数里用到了父类的成员变量,这个变量对于这个函数来说是个外部变量

#8


那么对于base.XXX 等等调用也是一样,只要动态地设置好 this 就能准确实现面向对象机制。其实一个方法不论是定义在父类还是子类,都是可以被任何其它代码调用的(从这个角度看,面向对象机制在底层完全是基于结构化类库机制的),编译器来判断你的源代码中的base.XXX等调用的类型是否合法、是否兼容。而运行时CLR来负责设置正确的this指针,告诉你的代码“当前的对象环境”。

#9


子类可以重写父类的方法,这是面向对象基本特征,任何面向对象编程语言都必须实现这个要求。这没有什么“不一样”,不能实现它的就不是一个面向对象编程语言。

编译器保证了程序员只能“程序设计时”严格按照“继承”语法要求才“覆盖”类的成员,而不像“c指针”那样随意在运行时覆盖。

#10


按照你给出的代码
base.show();
相当于
Console.WriteLine(base.a);

方法是方法,变量是变量

#11


#4楼贴出的 public new void show() 这类代码,这是违背面向对象编程原则的。如果说.net的这个机制是“ C# 与其他面向对象的语言不一样”,你也可以这样说。但是这并不是为了实现面向对象技术而有的!

实现这样的东西,应该是15年前考虑与微软自己的c++开发平台相兼容,为了将c++程序员引入c#平台。这个语法应该算是个“糟粕”。既然明知道 A 类的 show 方法是个异类而特意要写 new 关键字来声明,那么为什么不直接为 A 的这个与父类show毫无关系的方法另外起个名字(例如叫做show1)呢?

c++中无需声明new关键字就可以随便定义一个show。在.net中强迫程序员必须在A类写上new关键字才能定义这个show,这是很尴尬的事情,主要还是因为当时不舍得删除这个功能。

我们禁用“new”这个东西。这个时候就另外为方法起个名字(例如叫做show1)就可以了。

#12


引用 4 楼 xuzuning 的回复:
真的是你们说的那样吗?
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show();
        }
    }

    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a);
        }
    }
    class A : T
    {
        public new int a = 2;
        public int b = 3;
        public new void show()
        {
            Console.WriteLine("{0} {1}", a, b);
            base.show();
        }
    }
子类通过base等关键字调用父类的成员函数


你这是在偷梁换柱

#13


引用 4 楼 xuzuning 的回复:
真的是你们说的那样吗?
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show();
        }
    }

    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a);
        }
    }
    class A : T
    {
        public new int a = 2;
        public int b = 3;
        public new void show()
        {
            Console.WriteLine("{0} {1}", a, b);
            base.show();
        }
    }
子类通过base等关键字调用父类的成员函数

这就是我说的,毫无必要的继承。

#14


无论是偷梁换柱,还是毫无必要的继承
只要 C# 没有发出错误警告,那么他的表现就应该是一致的
子类继承了父类的方法,却不能访问子类自己的属性。这怎么都是说不过去的
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show(); //这里输出的是 1
        }
    }
 
    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a); 
        }
    }
    class A : T
    {
        public new int a = 2;
    }

#15


引用 14 楼 xuzuning 的回复:
无论是偷梁换柱,还是毫无必要的继承
只要 C# 没有发出错误警告,那么他的表现就应该是一致的
子类继承了父类的方法,却不能访问子类自己的属性。这怎么都是说不过去的
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show(); //这里输出的是 1
        }
    }
 
    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a); 
        }
    }
    class A : T
    {
        public new int a = 2;
    }


c# 语法告诉你了,你必须写new,这根本不是继承。这就跟 lz 问题中所讨论的继承机制无关系。

你看到的“不能访问a”才是正确的执行结果,因为你的 int new a 相当于另外定义了一个变量 int b,根本就跟继承来的变量 a 毫无关系。

#16


“C# 没有发出错误警告”,那是它以为你了解这种写法的意义。我认为这种 new 语法是“糟粕”,因为它是破坏面向对象概念而引起误解的。C#语法当然不能明说,它又不是论坛。

#17


那个属性 b 是我观察在父类方法里是否能访问的,没有删掉并不影响讨论

楼主的  被调用的父类成员函数是在父类的变量参数环境下执行,还是在子类的变量参数环境下执行 就是我描述的这种情况
事实证明:父类成员函数是在父类的变量参数环境下执行,与子类无关(虽然子类可在方法里修改父类的属性值并修改有效)
也就是说,子类声明的属性是不能覆盖掉父类的属性的
这表示类的属性是具有静态特征的,这一点与其他语言是不同的

#18


子类继承了父类的方法,却不能访问子类自己的属性。这怎么都是说不过去的

你不new int a,那么访问的就是子类自己的属性了



        public class A
        {
            public int a = 1;
            public void show()
            {
                MessageBox.Show(a.ToString());
            }
        }

        public class B : A
        {
        }

public class Form1:Form
{
        private void button2_Click(object sender, EventArgs e)
        {
            B b = new B();
            b.a = 2;
            b.show();//此处显示的是2,而不是1
}


你new int a
其实就相当于int b
那么你修改了b的值,却打印a的值,这跟继承有什么关系,完全是逻辑上的错误

#1


继承后的对象是一个有机的整体。
好比亚洲象是大象的一种,不是说每只亚洲象的肚子里藏着一只大象。

#2


如果要是派生类自己还有一套“环境参数”,那它还要继承基类干嘛。

#3


成员函数也不过是个函数

这跟写成public static形式的函数有什么区别吗

函数的参数是你自己传进去的啊

除非函数代码里还用到了外部变量

#4


真的是你们说的那样吗?
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show();
        }
    }

    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a);
        }
    }
    class A : T
    {
        public new int a = 2;
        public int b = 3;
        public new void show()
        {
            Console.WriteLine("{0} {1}", a, b);
            base.show();
        }
    }
子类通过base等关键字调用父类的成员函数

#5


引用 4 楼 xuzuning 的回复:
真的是你们说的那样吗?


不矛盾
你这个父类函数里用到了父类的成员变量,这个变量对于这个函数来说是个外部变量

#6


引用 楼主 jiang_198901 的回复:
还是在子类的变量参数环境下执行(把父类函数拷贝到子类中执行)?


可以这样理解。方法(以及属性、事件等等所有可继承的东西)可以看作是“按表格查找地址”的,方法代码其实并不属于任何具体的对象。

按照基本的操作系统原理,进程的数据区域跟代码区域其实是分离的。

只不过在代码被call(调用)时.net环境为它实现好了 this 关键字的引用,从而你在方法里的所有关于“当前对象”的引用都动态设置好了。这个this应该就是你所谓的“子类环境”。而实际的实现机制其实异常简单,就是由CLR设置好 this 就行了,并不会低效率地真去“拷贝”一大堆东西。

#7


那么类继承时,类的成员属性不会被覆盖吗?
为何 C# 与其他面向对象的语言不一样呢?

引用 5 楼 Z65443344 的回复:
Quote: 引用 4 楼 xuzuning 的回复:

真的是你们说的那样吗?


不矛盾
你这个父类函数里用到了父类的成员变量,这个变量对于这个函数来说是个外部变量

#8


那么对于base.XXX 等等调用也是一样,只要动态地设置好 this 就能准确实现面向对象机制。其实一个方法不论是定义在父类还是子类,都是可以被任何其它代码调用的(从这个角度看,面向对象机制在底层完全是基于结构化类库机制的),编译器来判断你的源代码中的base.XXX等调用的类型是否合法、是否兼容。而运行时CLR来负责设置正确的this指针,告诉你的代码“当前的对象环境”。

#9


子类可以重写父类的方法,这是面向对象基本特征,任何面向对象编程语言都必须实现这个要求。这没有什么“不一样”,不能实现它的就不是一个面向对象编程语言。

编译器保证了程序员只能“程序设计时”严格按照“继承”语法要求才“覆盖”类的成员,而不像“c指针”那样随意在运行时覆盖。

#10


按照你给出的代码
base.show();
相当于
Console.WriteLine(base.a);

方法是方法,变量是变量

#11


#4楼贴出的 public new void show() 这类代码,这是违背面向对象编程原则的。如果说.net的这个机制是“ C# 与其他面向对象的语言不一样”,你也可以这样说。但是这并不是为了实现面向对象技术而有的!

实现这样的东西,应该是15年前考虑与微软自己的c++开发平台相兼容,为了将c++程序员引入c#平台。这个语法应该算是个“糟粕”。既然明知道 A 类的 show 方法是个异类而特意要写 new 关键字来声明,那么为什么不直接为 A 的这个与父类show毫无关系的方法另外起个名字(例如叫做show1)呢?

c++中无需声明new关键字就可以随便定义一个show。在.net中强迫程序员必须在A类写上new关键字才能定义这个show,这是很尴尬的事情,主要还是因为当时不舍得删除这个功能。

我们禁用“new”这个东西。这个时候就另外为方法起个名字(例如叫做show1)就可以了。

#12


引用 4 楼 xuzuning 的回复:
真的是你们说的那样吗?
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show();
        }
    }

    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a);
        }
    }
    class A : T
    {
        public new int a = 2;
        public int b = 3;
        public new void show()
        {
            Console.WriteLine("{0} {1}", a, b);
            base.show();
        }
    }
子类通过base等关键字调用父类的成员函数


你这是在偷梁换柱

#13


引用 4 楼 xuzuning 的回复:
真的是你们说的那样吗?
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show();
        }
    }

    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a);
        }
    }
    class A : T
    {
        public new int a = 2;
        public int b = 3;
        public new void show()
        {
            Console.WriteLine("{0} {1}", a, b);
            base.show();
        }
    }
子类通过base等关键字调用父类的成员函数

这就是我说的,毫无必要的继承。

#14


无论是偷梁换柱,还是毫无必要的继承
只要 C# 没有发出错误警告,那么他的表现就应该是一致的
子类继承了父类的方法,却不能访问子类自己的属性。这怎么都是说不过去的
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show(); //这里输出的是 1
        }
    }
 
    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a); 
        }
    }
    class A : T
    {
        public new int a = 2;
    }

#15


引用 14 楼 xuzuning 的回复:
无论是偷梁换柱,还是毫无必要的继承
只要 C# 没有发出错误警告,那么他的表现就应该是一致的
子类继承了父类的方法,却不能访问子类自己的属性。这怎么都是说不过去的
    class Program
    {
        static void Main(string[] args)
        {
            A p = new A();
            p.show(); //这里输出的是 1
        }
    }
 
    class T
    {
        public int a = 1;
        public void show()
        {
            Console.WriteLine(a); 
        }
    }
    class A : T
    {
        public new int a = 2;
    }


c# 语法告诉你了,你必须写new,这根本不是继承。这就跟 lz 问题中所讨论的继承机制无关系。

你看到的“不能访问a”才是正确的执行结果,因为你的 int new a 相当于另外定义了一个变量 int b,根本就跟继承来的变量 a 毫无关系。

#16


“C# 没有发出错误警告”,那是它以为你了解这种写法的意义。我认为这种 new 语法是“糟粕”,因为它是破坏面向对象概念而引起误解的。C#语法当然不能明说,它又不是论坛。

#17


那个属性 b 是我观察在父类方法里是否能访问的,没有删掉并不影响讨论

楼主的  被调用的父类成员函数是在父类的变量参数环境下执行,还是在子类的变量参数环境下执行 就是我描述的这种情况
事实证明:父类成员函数是在父类的变量参数环境下执行,与子类无关(虽然子类可在方法里修改父类的属性值并修改有效)
也就是说,子类声明的属性是不能覆盖掉父类的属性的
这表示类的属性是具有静态特征的,这一点与其他语言是不同的

#18


子类继承了父类的方法,却不能访问子类自己的属性。这怎么都是说不过去的

你不new int a,那么访问的就是子类自己的属性了



        public class A
        {
            public int a = 1;
            public void show()
            {
                MessageBox.Show(a.ToString());
            }
        }

        public class B : A
        {
        }

public class Form1:Form
{
        private void button2_Click(object sender, EventArgs e)
        {
            B b = new B();
            b.a = 2;
            b.show();//此处显示的是2,而不是1
}


你new int a
其实就相当于int b
那么你修改了b的值,却打印a的值,这跟继承有什么关系,完全是逻辑上的错误