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

450160193 2015-04-27 09:25:11
在调用父类成员函数时,被调用的成员函数是在父类的变量参数环境下执行(跳转到父类执行),还是在子类的变量参数环境下执行(把父类函数拷贝到子类中执行)?
...全文
391 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
“C# 没有发出错误警告”,那是它以为你了解这种写法的意义。我认为这种 new 语法是“糟粕”,因为它是破坏面向对象概念而引起误解的。C#语法当然不能明说,它又不是论坛。
  • 打赏
  • 举报
回复
引用 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 毫无关系。
xuzuning 2015-04-27
  • 打赏
  • 举报
回复
无论是偷梁换柱,还是毫无必要的继承 只要 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;
    }
threenewbee 2015-04-27
  • 打赏
  • 举报
回复
引用 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();
        }
    }
这就是我说的,毫无必要的继承。
Liekkas 2015-04-27
  • 打赏
  • 举报
回复
引用 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();
        }
    }
你这是在偷梁换柱
  • 打赏
  • 举报
回复
#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)就可以了。
於黾 2015-04-27
  • 打赏
  • 举报
回复
按照你给出的代码 base.show(); 相当于 Console.WriteLine(base.a); 方法是方法,变量是变量
  • 打赏
  • 举报
回复
子类可以重写父类的方法,这是面向对象基本特征,任何面向对象编程语言都必须实现这个要求。这没有什么“不一样”,不能实现它的就不是一个面向对象编程语言。 编译器保证了程序员只能“程序设计时”严格按照“继承”语法要求才“覆盖”类的成员,而不像“c指针”那样随意在运行时覆盖。
  • 打赏
  • 举报
回复
那么对于base.XXX 等等调用也是一样,只要动态地设置好 this 就能准确实现面向对象机制。其实一个方法不论是定义在父类还是子类,都是可以被任何其它代码调用的(从这个角度看,面向对象机制在底层完全是基于结构化类库机制的),编译器来判断你的源代码中的base.XXX等调用的类型是否合法、是否兼容。而运行时CLR来负责设置正确的this指针,告诉你的代码“当前的对象环境”。
xuzuning 2015-04-27
  • 打赏
  • 举报
回复
那么类继承时,类的成员属性不会被覆盖吗? 为何 C# 与其他面向对象的语言不一样呢?
引用 5 楼 Z65443344 的回复:
[quote=引用 4 楼 xuzuning 的回复:] 真的是你们说的那样吗?
不矛盾 你这个父类函数里用到了父类的成员变量,这个变量对于这个函数来说是个外部变量[/quote]
  • 打赏
  • 举报
回复
引用 楼主 jiang_198901 的回复:
还是在子类的变量参数环境下执行(把父类函数拷贝到子类中执行)?
可以这样理解。方法(以及属性、事件等等所有可继承的东西)可以看作是“按表格查找地址”的,方法代码其实并不属于任何具体的对象。 按照基本的操作系统原理,进程的数据区域跟代码区域其实是分离的。 只不过在代码被call(调用)时.net环境为它实现好了 this 关键字的引用,从而你在方法里的所有关于“当前对象”的引用都动态设置好了。这个this应该就是你所谓的“子类环境”。而实际的实现机制其实异常简单,就是由CLR设置好 this 就行了,并不会低效率地真去“拷贝”一大堆东西。
於黾 2015-04-27
  • 打赏
  • 举报
回复
引用 4 楼 xuzuning 的回复:
真的是你们说的那样吗?
不矛盾 你这个父类函数里用到了父类的成员变量,这个变量对于这个函数来说是个外部变量
xuzuning 2015-04-27
  • 打赏
  • 举报
回复
真的是你们说的那样吗?
    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();
}
}
於黾 2015-04-27
  • 打赏
  • 举报
回复
成员函数也不过是个函数 这跟写成public static形式的函数有什么区别吗 函数的参数是你自己传进去的啊 除非函数代码里还用到了外部变量
threenewbee 2015-04-27
  • 打赏
  • 举报
回复
如果要是派生类自己还有一套“环境参数”,那它还要继承基类干嘛。
threenewbee 2015-04-27
  • 打赏
  • 举报
回复
继承后的对象是一个有机的整体。 好比亚洲象是大象的一种,不是说每只亚洲象的肚子里藏着一只大象。
於黾 2015-04-27
  • 打赏
  • 举报
回复
子类继承了父类的方法,却不能访问子类自己的属性。这怎么都是说不过去的 你不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的值,这跟继承有什么关系,完全是逻辑上的错误
xuzuning 2015-04-27
  • 打赏
  • 举报
回复
那个属性 b 是我观察在父类方法里是否能访问的,没有删掉并不影响讨论 楼主的 被调用的父类成员函数是在父类的变量参数环境下执行,还是在子类的变量参数环境下执行 就是我描述的这种情况 事实证明:父类成员函数是在父类的变量参数环境下执行,与子类无关(虽然子类可在方法里修改父类的属性值并修改有效) 也就是说,子类声明的属性是不能覆盖掉父类的属性的 这表示类的属性是具有静态特征的,这一点与其他语言是不同的

110,526

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧