C#多态实现以及基类与派生类引用类型相互转换的原理
多态实现原理
编译器在编译的时候为每一个含有虚函数的类分配一个虚函数表,生成对象的时候为每一个对象分配一个虚表指针,指向本类的虚函数表。在程序运行期间,当用派生类的对象给基类引用赋值时,就会用派生类的虚表指针覆盖基类的虚表指针,因此在用基类指针调用该方法的时候总能正确的指向派生类所重写的方法.
伪代码:
class A
{ virtual func()}
class B:A
{ func() }
主函数:
A a = new B()
a.func()
-----此时调用的时B中的func 方法,由此实现多态。
A a = new B(),此步骤主要做了三件事:
1.A a – 生成了一个A为模板的引用类型(类似与c/c++中指针变量,实际并没有分配对象内存)。
2. new B()----生成了一个B的对象(分配了内存空间)
3. 将a 引用指向B生成的对象。
我们 知道,当类B继承了类A的时候,B就拥有了A的所有方法及属性。
而此时的引用类型a 则被限定只能调用A范围内的属性方法,调用B方法时会报错。(类A的框没有装B的属性方法)
如果A中的方法为 普通方法,在用a调用的时候就会调用 A中的方法,此为编译期间就决定。如下代码区的tbase.PrintHelloWorld()实际上调用类A 中的方法。
若如果A中的方法为虚方法,调用时则根据多态原理在运行期间覆盖虚指针而实际调用B中方法。如下代码区的tbase.PrintName();
如何用 a 调用B 中方法呢
用强制类型转换把A类型的引用类型强转成B类型(把A的框放大成B了)
TestData tdata = (TestData)tbase;
此时的tdata 就可以访问所有的B属性包括A属性 以及B特有属性。
但是其中有个问题,如果A中方法与B中方法重名----- 如代码中PrintHelloWorld(),此时调用的为何是B中的方法?如输出的第6行
这涉及到派生类对基类方法的 隐藏。
隐藏方法:可以用与基类成员名称相同的成员来屏蔽基类成员。
隐藏数据成员:在派生类中声名名称和类型相同的成员,不需要new关键字。
隐藏函数成员:在派生类中声名新的带有相同函数签名的成员(函数名和函数参数相同即可,对返回值类型无要求),在声名前面加上new关键字。
在此不赘述
—以上为学习过程中记录和感悟。如有错误,欢迎指出。评论区对线哈哈哈