当前位置:首页 >> 电子/电路 >>

8论述C#与C 在继承性和多态性上的异同


论述 C#与 C++在继承性和多态性上的异同
C++语言是一种同时支持面向过程程序设计和面向对象程序设计的混合型高级程序设计 语言。C++支持封装性、继承性和多态性。C#是从 C 和 C++语言演化而来的,它在语句、表 达式和运算符方面沿用了许多 C++的功能,同时也有着相当大的改进和创新。为了提高软件 模块的可复用性和可扩充性, 以便提高软件的开发效率, 我们总是希望能够利用前人或自己 以前的开发成果, 同时又希望在自己的开发过程中能够有足够的灵活性, 不拘泥于复用的模 块。C#这种完全面向对象的程序设计语言提供了两个重要的特性--继承性和多态性。 一、继承性: 继承是面向对象程序设计的主要特征之一, 它可以让您重用代码, 可以节省程序设计的 时间。 继承就是在类之间建立一种相交关系, 使得新定义的派生类的实例可以继承已有的基 类的特征和能力,而且可以加入新的特性或者是修改已有的特性建立起类的新层次。 我们从 C#的派生和 C++的派生类的定义格式和例子来分析。 (1)C#: [访问修饰符] class 类名[:基类名] { 类的成员; }; 例子: using System; public class Person //这是一个基类 { //定义数据成员 public string Name; //姓名 public char Sex; //性别 //定义构造函数,以初始化字段 public Person(string name, char sex) { Name = name; Sex = sex; } //定义方法成员 public string Answer() { return string.Format("姓名:{0},性别:{1}。", Name, Sex); } } public class Student : Person { //扩展数据成员 //这是一个派生类

public string School; //学校 private int Score; //成绩 //定义构造函数,自动调用基类的构造函数辅助完成字段的初始化 public Student(string name, char sex, string school, int score) : base(name, sex) { School = school; Score = score; } //扩展方法成员 public float Examine() //返回考试成绩 { return Score; } } class TestClass { static void Main() { //创建Student对象 Student s = new Student("张伟", '男', "电子科大成都学院", 480); Console.WriteLine("该生信息如下:"); Console.WriteLine(s.Answer()); //调用对象继承来的方 法 Console.WriteLine("学校:{0},考试成绩:{1}", s.School, s.Examine()); } } (2)C++: Class <派生类名>: [继承方式]<基类名 1>[, [继承方式]<基类名 2>, ````[继承方式]< 基类名 3>] { <派生类新增的数据成员和成员函数定义> }; 例子: typedef char string80[80]; class Date { public: Date() {} Date(int y, int m, int d) { SetDate(y, m, d); } void SetDate(int y, int m, int d) { Year = y;

Month = m; Day = d; } void GetStringDate(string80 &Date) { sprintf(Date, "%d/%d/%d", Year, Month, Day); } protected: int Year, Month, Day; }; class Time { public: Time() {} Time(int h, int m, int s) { SetTime(h, m, s); } void SetTime(int h, int m, int s) { Hours = h; Minutes = m; Seconds = s; } void GetStringTime(string80 &Time) { sprintf(Time, "%d:%d:%d", Hours, Minutes, Seconds); } protected: int Hours, Minutes, Seconds; }; class TimeDate:public Date, public Time { public: TimeDate():Date() {} TimeDate(int y, int mo, int d, int h, int mi, int s):Date(y, mo, d), Time(h, mi, s) {} void GetStringDT(string80 &DTstr) { sprintf(DTstr, "%d/%d/%d;%d:%d:%d", Year, Month, Day, Hours, Minutes, Seconds); } }; void main() {

TimeDate date1, date2(1998, 8, 12, 12, 45, 10); string80 DemoStr; date1.SetDate(1998, 8, 7); date1.SetTime(10, 30, 45); date1.GetStringDT(DemoStr); cout<<"The date1 date and time is:"< date1.GetStringDate(DemoStr); cout<<"The date1 date is:"< date1.GetStringTime(DemoStr); cout<<"The date1 time is:"< date2.GetStringDT(DemoStr); cout<<"The date2 date and time is:"< } 首先,我们比较 C++源代码中的第 C 行和 C#源代码中的第 C 行。我们可以看到在 C++中 的继承是分为: 公有继承,私有继承,保护继承。而在 C#中只有默认的公有继承。这样简 化了继承的方式, 至于限制派生类访问基类的数据以及方法成员, 将由基类的数据以及方法 成员的访问控制权限决定。 (1) C#中,派生类只能从一个类中继承。这是因为,在 C++中,人们在大多数情况下不 需要一个从多个类中派生的类。从多个基类中派生一个类,往往会带来许多问题,从而抵消 了这种灵活性带来的优势。 C#中的继承符合下列规则: 继承是可传递的。 如果 C 从 B 中派生, B 又从 A 中派生, 那么 C 不仅继承了 B 中声明的成员, 同样也继承了 A 中的成员。 Object 类 作为所有类的基类。 (2) 派生类应当是对基类的扩展。派生类可以添加新的成员,但不能除去已经继承的成 员的定义。构造函数和析构函数不能被继承。除此以外的其它成员,不论对它们定义了怎样 的访问方式,都能被继承。基类中成员的访问方式只能决定派生类能否访问它们。 (3) 派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已继承的成员。但 这并不因为这派生类删除了这些成员,只是不能再访问这些成员。类可以定义虚方法、虚属 性以及虚索引指示器,它的派生类能够重载这些成员,从而使得类可以展示出多态性。 (4) C#中,派生类只能从一个类中继承,但可以通过接口实现多重继承。

在 C#中可以通过 base 关键字来访问基类成员,具体的访问规则如下: (1) 调用基类上已被其他方法重写的方法。 (2) 指定创建派生类实例时应调用的基类构造函数。 (3) 基类访问只能在构造函数、实例方法或实例属性访问器中进行。 (4) 从静态方法中使用 base 关键字是错误的。 我们能看出来两者不同之处, (1)C#中,派生类只能从一个类中继承,但 C++中有单一 继承,多重继承和多极继承。 (2)C#的默认继承方式是 public,而 C++的默认继承方式是 private。C++可以从多个基类中继承下来,每个基类都要设定继承方式。 两者的相同之处(1)派生类从它们的直接基类中继承成员:方法、域、属性、事件、 索引指示器。 (2)私有成员,构造函数和析构函数都不能被继承。 (3)派生类应当是对基类 的扩展。派生类可以添加新的成员,但不能除去已经继承的成员的定义。 (4)运行时,派生 类对构造函数和析构函数的顺序一样。 (3)派生类中的构造函数都用 base 来引用基函数构 造函数来给基函数的成员赋初值。 C#中在属性的重载中,提出了密封属性。用 sealed 修饰符声明的属性为密封属性。类

的密封属性不允许在派生类中被继承。密封属性的访问器同样也是密封的。C#和 C++在访问 派生类与基类同名成员时,有所不同,因为 C#每一个派生类只有一个基类,访问基类成员 时通过 base 关键字访问。C++的继承有多种方式,可能有一个基类,也可能有几个基类, 所以访问基类的成员时,通过:基类名: :成员名,来达到访问目的。

二、多态性: 在面向对象的系统中, 多态性是一个非常重要的概念, 它允许客户对一个对象进行操作, 由对象来完成一系列的动作,具体实现哪个动作,如何实现由系统负责解释。 多态性的定义是:同一操作作用于不同的类的实例,不同的类将进行不同的解释,最后 产生不同的执行结果。C#和 C++均支持两种类型的多态性:编译时多态性和运行时多态性。 前者是在编译的过程中确定了同名操作的具体操作对象, 而后者则是程序运行过程中动态地 确定操作所针对的具体对象。 这种确定具体对象的过程就是联编。 联编是指计算机程序自身 彼此关联的过程, 也就是把一个标识符名和一个存储地址联系在一起的过程: 用面向对象的 术语讲,就是把一条消息和一个对象的方法相结合的过程。按照联编进行的阶段的不同,可 以分为两种不同的联编方法: 静态联编和动态联编, 这两种联编过程分别对应着多态的两种 实现方式。 (一)分析 C++与 C#中重载多态性: 在 C++和 C#编译器都有自己的一些算法用于重新解析。 为了进行重新解析, 函数以它的 签名来表示,签名就是函数名加上它的参数列表(参数的数量以及每个参数的类型) 。但两 者的同之处在于: C++中是允许把高级转化为低级,例如 long 转换为 int 类型进行函数调 用的。但是在 C#中是不允许把 double 转换为 int 类型的。即 C#中不允许进行收缩转换,因 为有可能会使内存产生溢出。如果非要转换的话,就必须使用类型强制转换符。 (二)分析 C++与 C#中运算符重载多态性: 运算符重载是对已经有的运算符赋予多重含义, 使同一个运算符作用于不同的类型的数 据导致不同类型的行为。运算符重载实质就是函数重载。在实现过程中,首先把指定的运算 表达式转换为对运算符函数的调用, 运算对象转化为运算符函数的实参, 然后根据实参的类 型来确定需要调用的函数,这个过程是在编译过程中完成的。 C++的运算符重载的规则如下: (1)C++中运算符除了类属关系运算符 “.” 、 成员指针运算符 “*” 、 作用域分辨符号 “: : ” 、 sizeof 运算符和三目运算符“?”不能被重载,其他的都可以重载,但只能重载 C++中已有 的运算符。 (2)重载之后运算符的优先级和结合性都不会改变。 (3)运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来 讲,重载的功能应当与原有的功能相类似,不能改变原运算符的操作对象个数,同时至少要 有一个操作对象是自定义类型。 C#中的操作符重载的作用与 C++是一致的,但是 C#中的操作符重载也有其自己的特点。 如下所示: (1)C#中,操作符重载总是在类中进行声明,并且通过调用类的成员方法来实现。操作 符重载声明的格式为:type operator operator-name(formal-param-list) (2) C#中不能被重载的操作符:=、&&、||、?: 、new、typeof、sizeof、is 其他的都 可以重载,但只能重载 C#中已有的运算符。 两者唯一不同之处在于 C#中的运算符重载函数必须是静态的。

(三)C++与 C#中强制多态性分析: 数据类型的转换就是,将存储在变量中的数值由一种类型转换成另外一种类型。在 C++ 中,数据类型转换可以是隐式的,也可以是显式的: float I = 100.1; long j = I; //隐式转换 int k = (int)I; //显式转换 int m=int(I); //显式转换,新 C++风格 C++中, 有两种显式的数据类型转换格式——旧的 C 风格, 其中数据类型名放在括号内。 新风格,其中变量名放在括号内。在 C#中,显式转换数据类型总是用旧的 C 风格语法,不 能用 C++新的风格。C#的类型安全性要比 C++要高,所以它的数据间的转换不灵活。C#的显 式转换和隐式转换都是正式的转换。定义为隐式的转换可以用显式或隐式两种转换来执行。 而对定义为显式转换的数据转换使用隐式转换会出现错误。这点与 C++不同,C++只会出现 警告。 (四)C++与 C#中包含多态性分析: 包含多态性是指通过继承提供多态性。 包含多态性反映了能够在多于一个类的对象中完 成同一事物的能力——用同一种方法在不同的类中处理不同的对象。 包含多态性是运行时多 态。 C#和 C++都通过继承来为我们提供包含多态性。它们均提供了 virtual 关键字用于定义 一个支持多态的方法。子类对于虚拟方法可以自由地提供它自己的实现,这称为重写。下面 是一些关于 C#虚拟方法的要点: (1) 如果方法是非虚拟的,编译器简单地使用所引用的类型来调用适当的方法。 (2) 如果方法是虚拟的,编译器将产生代码来在运行时检查所引用的类,来从适当的类 型中调用适当的方法。 (3) 当一个虚拟方法被调用时,运行时会进行检查(方法迟绑定)来确定对象和调用适 当的方法,所有这些都是在运行时进行的。 对于非虚拟方法,这些信息在编译期间都是无效的,因此不会引起运行时检查,所以调 用非虚拟方法的效率会略微高一些。 但在很多时候虚拟方法的行为会更有用, 损失的那些性 能所换来的功能是很值得的。 在 C++和 C#中包含多态性是很类似的, 他们均是通过虚函数来 实现的。通过下面的代码来分析它们间的异同。 C#中可以用两种方法来实现类成员的多态性:一是使用 new 关键字重新定义类的成员, 看一例子: Public class Pesrson { Public string id; Public string Name; Public string Answer() { Return string.Format(“工作证号:{0},姓名:{1}。”,id,Name); } } Public class Student : Person { Public new string Answer() {

Return string.Format(“学号:{0},姓名:{1}。”,id,Name); } } C#和 C++均提供了 virtual 关键字用于定义一个支持多态的方法。 我们直接看两个例子再来分析: C#: using System; namespace duotai3 { using System ; public class DrawingBase { public virtual void Draw( ) { Console.WriteLine("I‘m just a generic drawing object.") ; } } public class Line : DrawingBase { public override void Draw( ) { Console.WriteLine("I‘m a Line.") ; } } public class Circle : DrawingBase { public override void Draw( ) { Console.WriteLine("I ‘ m a Circle.") ; } } public class Square : DrawingBase { public override void Draw( ) { Console.WriteLine("I ‘ m a Square.") ; } } public class DrawDemo {

public static void Main(string[] args) { DrawingBase [] dObj = new DrawingBase [4]; dObj[0] dObj[1] dObj[2] dObj[3] = = = = new new new new Line( ) ; Circle( ) ; Square( ) ; DrawingBase( ) ;

foreach (DrawingBase drawObj in dObj) drawObj.Draw( ) ; } } } 程序运行结果: I‘m a Line ! I‘m a Circle ! I‘m a Square ! I‘m just a generic drawing object! C++: #include<iostream> using namespace std; class DrawingBase { public: virtual void Draw() { cout<<"I‘m just a generic drawing object!"<<endl; } }; class Line:public DrawingBase { public : virtual void Draw() { cout<<"I‘m a Line !"<<endl; } }; class Circle:public DrawingBase {

public: virtual void Draw() { cout<<"I‘m a Circle !"<<endl; } }; class Square:public DrawingBase { public: void Draw() (A) { cout<<"I‘m a Square !"<<endl; } }; void main() { DrawingBase *dObj[4]; dObj[0] = new Line( ) ; dObj[1] = new Circle( ) ; dObj[2] = new Square( ) ; dObj[3] = new DrawingBase( ) ; for(int i=0;i<4;i++) dObj[i]->Draw(); system("pause"); } 程序运行结果: I‘m a Line ! I‘m a Circle ! I‘m a Square ! I‘m just a generic drawing object! 我们能很清楚地从上面两个例子看出来在实现类的包含多态性用虚函数实现的时 候,C++与 C#有一个非常重要的区别:正如我前面所说,在 C++中可以在派生类中省略掉 virtual 虚函数关键字,但是在 C#中必须在派生类中虚拟函数使用 override 关键字,否则 编译器不会把他当成虚拟函数,该派生类也不会具有多态性。 C#中字段不能是虚拟的,只有方法,属性,事件和索引器可以是虚拟的。C++静态成员 函数,构造函数,内联函数都不能为虚,而析构函数往往被声明为虚函数。

//


赞助商链接
相关文章:
C,C++,C#三者区别
C与C++的部分区别 8页 1下载券 C++与C的区别 2...C#是微软弄的一个东东,继承了 C 和 C++的许多...对于多态对象来说, 也就意味着构造函数在背后执行了...
c#实验一 继承与多态编程练习
2.掌握 Visual C#.NET 类的创建(成员,方法,属性),类的继承,类的 多态性及...C程序设计与应用实验指导... 14页 免费 C++程序设计 第8章 继承... 111页...
C#第一套试题及答案
4. C#中接口和类有什么异同? 答:类是引用类型,...C(读 c sharp),它可以看 作是 VC Java 的...继承性和多态性使得代码的可重用性大大提高,你可 ...
第8章 继承与多态性习题参考答案
C++程序设计语言习题及实验指导 第 8 章 继承与多态性习题参考答案 8.3 8.3.1 选择题 题号 答案 题号 答案 1 C 11 D 2 D 12 D 3 A 13 A 4 D 14...
C#复习题
16.在 C#.Net 中,用来创建主菜单的对象是( C A...8. 枚举是从 System. Enum default 封装 语句时,...11.面向对象的语言具有继承性多态性和__封装性_...
c#一兼答案
C#模拟练习 一.选择填空 1. 面向对象的语言具有继承性多态性和___性。 A...A)整型 B)字符型 C)任意类型 D)数组 8.在 c#中 using 关键字的作用是__...
C#与CC++的交互
C/C++与 C#中有一些数据类型长度是不一样的,下表中列出常见数据类型的异同: ...8 Bytes double 最容易弄混的是就是 long,char 两个类型,在 C/C++中 long ...
C#多态之我见
关键词:C#多态 1/2 相关文档推荐 C_多态 14页 ...7.类的多态性 63页 免费 第8章 继承与多态 33页...组件编程中的一项强大技术是能够在一个对象上实现多...
...设计教程》第8章动物类派生——继承与多态
C# 3.0项目导向与实训程序设计教程》第8章动物类...3. 能运用继承与多态性编写哺乳动物类派生马类鲸鱼...(a) 图 8-1 (b) (c) 哺乳动物类派生马类...
第8章 C#继承教案
第8章 C#继承教案_计算机软件及应用_IT/计算机_专业...③ 类的继承可以传递。例如,假设 C继承 B 类...多态性概述 在类的继承中,C#允许在基类与派生类中...
更多相关标签: