类继承
C++支持三种不同的继承方式:private、protected和public,继承方式只影响派生类外部对基类成员的访问权限,而不影响派生类在内部对基类成员的访问权限。私有继承意味着所有基类成员将被继承为派生类的私有成员;保护继承意味着基类所有public成员被继承为protected,其它成员不受影响;公有继承则保持基类成员的原有访问控制不变。例子:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 
 | class Base{
 private:
 int _ID;
 protected:
 char* _Name;
 public:
 void show(){cout<<_ID<<": "<<_Name;}
 }
 
 
 class Child1: private Base
 {
 private:
 
 void test()
 {
 name="";
 show();
 }
 }
 
 
 class Child2: protected Base
 {
 private:
 void test()
 {
 name="";
 show();
 }
 }
 
 class Child3: public Base
 {
 private:
 void test()
 {
 name="";
 show();
 }
 }
 
 
 class CChild1: public Child1
 {
 private:
 void test()
 {
 name="";
 show();
 }
 }
 
 
 class CChild2: public Child2
 {
 private:
 void test()
 {
 name="";
 show();
 }
 }
 
 Child1 c1;
 Child2 c2;
 c1.show();
 c2.show();
 
 | 
C++中的方法重写
解释方法重写前需要弄明白函数重载与方法重写的概念。函数重载发生在同一类作用域,而方法重写发生在类继承中,即使子类用不同的参数列表重写父类方法,他也不是重载,而是重写,例如:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | class Base{
 public:
 void show(){cout<<"base";}
 }
 
 class Child: public Base
 {
 public:
 void show(int i){cout<<"child";}
 }
 
 Child c;
 c.show();
 c.show(0);
 
 | 
发生重写时,函数的父类版本将被子类隐藏。
派生类重写基类虚方法时,要求子类保持方法签名一致,否则将变成上面的普通方法重写,子类将隐藏父类虚方法。例如:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | class Base{
 public:
 virtual void show() {cout<<"base";}
 }
 
 
 class Child: public Base
 {
 public:
 void show(int i) {cout<<"child";}
 }
 
 
 class Child1: public Base
 {
 public:
 void show(int i) {cout<<"child1";}
 void show() {cout<<"child1 virtual";}
 }
 Child c;
 c.show();
 Child1 c1;
 c1.show();
 c1.show(0);
 
 | 
.NET中的函数重写
当子类保持函数签名一致时,对于普通方法重写,需要显式指定new(Shadows)关键字;对于虚方法,需要显式指定override关键字
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 | class BaseCls{
 public virtual void show()
 {
 Console.WriteLine("Base");
 }
 }
 
 
 class ChildCls:BaseCls
 {
 public override void show()
 {
 Console.WriteLine("Child");
 }
 }
 
 
 class BadChildCls:BaseCls
 {
 public new void show()
 {
 Console.WriteLine("BadChild");
 }
 }
 
 BaseCls a,b;
 a=new ChildCls();
 b=new BadChildCls();
 a.show();
 b.show();
 
 
 
 
 
 
 | 
当子类方法与父类函数签名不一致时,.NET将其视为重写+重载,而不是像C++一样简单的隐藏父类方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 
 | //VB.NETClass BaseCls
 Public Overridable Sub Show()
 Console.WriteLine("base")
 End Sub
 End Class
 
 Class Child:Inherits BaseCls
 Public Overloads Sub Show(Byval i as Int32)
 Console.WriteLine("child")
 End Sub
 End Class
 
 Dim c as New Child
 c.Show(0)	//OK
 c.Show()	//OK
 
 //C#
 class BaseCls
 {
 public virtual void Show() {Console.WriteLine("base");}
 }
 
 class Child: BaseCls
 {
 public void Show(int i) {Console.WriteLine("child");}
 }
 
 Child c = new Child();
 c.Show();	//OK
 c.Show(0);	//OK
 
 | 
上述代码实际上可以拆分为:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | Class Child:Inherits BaseCls//方法重写
 Public Overrides Sub Show()
 MyBase.Show()
 End Sub
 
 //函数重载
 Public Overloads Sub Show(Byval i as Int32)
 Console.WriteLine("child")
 End Sub
 End Class
 
 | 
不过两者略有区别,通过查看生成的IL代码,第一种写法中Child只有Show(Int32)方法,对Show()的调用直接编译为MyBase.Show(),但使用反射仍然可以获取Child.Show()方法。