1)假设:
•B1
定义方法virtualM()
和nonvirtualM()
,其中前一种方法是虚拟的,而后一种方法是非虚拟的
•B2
来自B1
•B2
会覆盖virtualM()
•B2
在程序集A
内定义
•应用程序app
没有对程序集A
在以下代码应用程序app
中动态加载程序集A
,创建类型B2
的实例并调用方法virtualM()
和nonvirtualM()
:< / p>
Assembly asemb=Assembly.Load(“A”);
Type t= asemb.GetType(“B2”);
B1 a = ( B1 ) Activator.CreateInstance ( “t” );
a.virtualM();
a.nonvirtualM();
a)对a.virtualM()
的呼叫是否被视为早期绑定或后期绑定?
b)我假设在编译期间对a.nonvirtualM()
的调用已解决?
2)术语后期绑定是指仅在运行时查找目标方法还是指在运行时创建给定类型的实例?
感谢名单
编辑:
1)
- 我假设在编译期间解析了对a.nonvirtualM()的调用?
- 是的。
如果我们有:
A a = new A();
a.M();
据我所知,在编译时不知道在运行时是否在堆上创建实例a
的堆(因此在哪个内存地址)。
现在,通过早期绑定,在编译过程中将函数调用替换为内存地址。但是编译器如何用内存地址替换函数调用,如果它不知道堆在运行时会在哪里创建对象a
(这里我假设方法a.M
的地址也将是在与a
相同的内存位置?
2)
方法槽在编译时确定
我假设你通过方法槽指的是V-table中的入口点?
答案 0 :(得分:5)
a)对a.virtualM()的调用是否被认为是早期绑定或后期绑定?
由谁考虑?
方法槽在编译时确定。插槽的内容 - 实际调用的方法 - 在运行时确定。
因此,绑定可以说是“迟到”。
有些人说在编译时没有完全发生的任何绑定都是后期绑定。有些人说,部分在编译时和部分在运行时发生的虚拟绑定仍然算是“早期”,其他人不同意。我想几乎所有人都同意,如果插槽在运行时才确定,那肯定是后期绑定。
b)我假设在编译期间解析了对a.nonvirtualM()的调用?
是的。
2)术语后期绑定是指仅在运行时查找目标方法还是指在运行时创建给定类型的实例?
我从来没有听过“后期绑定”指的是创建实例。
答案 1 :(得分:2)
这里我假设方法a.M的地址也与“a”在同一个内存位置
这个假设是不正确的。
如果你有
class C { internal int x; public int M() { return this.x; } }
然后C的每个实例都没有得到它自己的M代码副本。它们共享M中代码的单个“副本”。你不会复制永不改变的代码;这会浪费你的记忆力。调用代码时:
C c = new C();
c.x = 123;
Console.WriteLine(c.M());
然后c的托管地址作为“this”传递,控制权转移到M代码的位置。该代码只有一个“副本”。
运行时知道M的代码在哪里,因为运行时是代码,因此它知道它在内存中的位置。
答案 2 :(得分:1)
1a)它是早期绑定
1b)是的。就像将其更改为a.nonexistentmethod()
一样,您将收到错误
2)两者都是后期绑定。