Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将派生类对象指定给父类引用_C#_Oop_Inheritance_Polymorphism - Fatal编程技术网

C# 将派生类对象指定给父类引用

C# 将派生类对象指定给父类引用,c#,oop,inheritance,polymorphism,C#,Oop,Inheritance,Polymorphism,当我看到: Parent ref = new Child(); 其中子类扩展父类 对象引用在内存中是什么样子的? 如何对待虚拟方法?非虚拟的? 它与: ref是一个子对象。对子类调用虚拟方法。但是,仅在子类中定义的方法在指定给父对象时不可见 如果foo不是虚拟的,那么编译器将根据变量ref的声明类型选择一个方法;然后将调用Parent.foo。如果您有Child ref=新的Child;然后将调用Child.foo。当然,在这种情况下,C编译器会要求您在Child.foo的声明中使用new来表

当我看到:

Parent ref = new Child();
其中子类扩展父类

对象引用在内存中是什么样子的? 如何对待虚拟方法?非虚拟的? 它与: ref是一个子对象。对子类调用虚拟方法。但是,仅在子类中定义的方法在指定给父对象时不可见

如果foo不是虚拟的,那么编译器将根据变量ref的声明类型选择一个方法;然后将调用Parent.foo。如果您有Child ref=新的Child;然后将调用Child.foo。当然,在这种情况下,C编译器会要求您在Child.foo的声明中使用new来表示您要在Parent中隐藏实现。

我想ref只包含可以找到引用的子对象的地址。如果调用虚拟方法,则实际调用的方法取决于对象子对象的动态类型;如果调用非虚拟方法,则它取决于静态类型父级。它不同于Child ref=。。。因为在这个例子中,静态类型是Child而不是Parent


我希望这不是家庭作业:

假设父类不是抽象类,就这样想吧

Parent ref = new Child();

它们基本上是相同的,除了在Child中重写的虚拟方法将在前者中调用,而不是在后者中调用

将对象声明为的类型将决定其上可用的方法。将对象声明为比前一种情况下实例化的对象更不特定的类型可能会影响在运行时调用哪些方法,但仅当这些方法声明为抽象或虚拟时

在这两种情况下,假设您在ref上调用了一个方法foo。运行时将在类Parent上调用方法foo。然后运行时将查看foo是虚拟的还是抽象的。如果foo不是虚拟的或抽象的,那么运行时将立即调用foo父定义,并使用它完成。然而,如果foo是虚拟的或抽象的,那么运行时将检查ref是否真的被实例化为一个覆盖foo的更具体的类型。如果是这样,它会称之为foo

对象在内存中的外观如何

你的问题不清楚。有两个相关的内存位置。该变量与存储位置相关联。该存储位置包含对另一存储位置的引用

该变量的存储位置通常实现为一个4或8字节的整数,其中包含一个托管指针—垃圾收集器已知的内存地址

对象的内存布局也是CLR的一个实现细节。与该对象关联的内存缓冲区将包含该对象的所有数据——字段的所有值等等。它还包含对另一个内存位置的引用,即对象的虚拟函数表

虚拟函数表vtable包含更多的引用,这次引用的是与派生类型最多的对象关联的方法

如何对待虚拟方法?非虚拟的

执行虚拟方法的方法是:从变量中查找对象引用,然后查找vtable,然后在vtable中查找方法,然后调用该方法

非虚拟方法不会通过vtable调用,因为它们在编译时是已知的

它与……有什么不同

在对象上调用的非虚拟方法将根据变量的类型调用方法的版本。对对象调用的虚拟方法将根据变量引用的对象类型调用方法的版本

如果这还不完全清楚,您可能希望阅读我的文章,其中解释了如何在没有虚拟方法的语言中模拟虚拟方法。如果您能够理解如何用一种没有虚拟方法的语言来实现虚拟方法,那么这将有助于您理解我们实际上是如何实现虚拟方法的


我希望不是,我讨厌被骗去回答家庭作业。我相信他的话,他为什么要问;“也许我应该放弃我的答案……我想让OP受益于怀疑,是吗?”斯图尔特·戈洛德茨-我说的绝对正确。如果他在作业上作弊,而我不是说他作弊,那么期末考试时间对他来说就更糟了。无论如何,这个问题是明确的、智能的,并且为堆栈溢出提供了良好的内容,而不是家庭作业。我是一名职业工作人员。我在采访中被问到这个问题,从那以后我一直感到困惑。尽量不要使用“ref”-这是一个关键字。如果foo在父类和子类中都作为非虚拟方法存在,并且ref.foo被调用。调用哪一个?将根据ref的类型调用该方法。如果您有Parent ref=new Child;然后将调用Parent.foo。如果您有Child ref=新的Child;然后将调用Child.foo。
我在回答中加了这个。@TingYun-我说得再清楚不过了,Dwilcox博士谢谢了。这就是我要找的。迄今为止最好的答案。
Parent ref = new Child();
Parent ref = new Parent();