C#与C++异同
C#与 C++异同
1 细微差异 ............................................................................................................................................................... 1
1.1 类的声明 .............................................................................
C#与 C++异同
1 细微差异 ............................................................................................................................................................... 1
1.1 类的声明 .................................................................................................................................................... 1
1.2 同名覆盖 .................................................................................................................................................... 1
2 多重继承 ............................................................................................................................................................... 1
3 C#虚方法和 C++中的虚
数 ................................................................................................................................. 3
4 数组 ....................................................................................................................................................................... 7
5 C#中按值传递和按引用传递 ................................................................................................................................. 7
6 字符串 ................................................................................................................................................................... 9
7 抽象类 ................................................................................................................................................................... 9
7.1 抽象类的构造函数................................................................................................................................... 11
8 C#类访问控制修饰符........................................................................................................................................... 13
9 C#中的类型转换 .................................................................................................................................................. 13
10 C#委托(delegate) ................................................................................................................................................ 14
11 C#中事件(event) ................................................................................................................................................. 17
12 接口(interface) ................................................................................................................................................... 19
12.1 接口的使用 ............................................................................................................................................ 19
12.2 接口的多继承 ........................................................................................................................................ 22
12.3 接口的重新实现..................................................................................................................................... 24
12.4 接口和多态 ............................................................................................................................................ 25
12.5 接口的应用举例..................................................................................................................................... 26
12.6 接口与抽象类的比较 ............................................................................................................................. 27
13 密封 ................................................................................................................................................................... 28
13.1 密封类 .................................................................................................................................................... 28
13.2 密封方法 ................................................................................................................................................ 28
1 细微差异
1.1 类的声明
C++的类声明结束后要在最后的大括号后面用分号结尾。C#则可用可不用,往往都是省略。
1.2 同名覆盖
C++中,如果基类和派生类有相同的成员,遵守同名覆盖原则,即派生类对象访问的是派生类的同名
成员,基类对象访问的是基类同名成员。
2 多重继承
C++可以多重继承,即一个派生类可以从多个基类同时继承,而 C#只能从一个类单重继承,但可以
通过接口实现多重继承。C++中如果基类和派生类中有相同成员时,遵循同名覆盖原则,即派生类对象使
用的是派生类同名成员,如果要在派生类中使用基类被覆盖的同名成员(称为派生类和基类互相通信)或
派生类外通过派生类对象访问基类同名成员,都必须使用基类名限定,如 A::f(),举例如下:
Class A
{
Public:
void f(){};
};
Class B:A
{
Public:
void f()
{
A::f();//在派生类中访问基类成员 f(),互相通信
}
};
1
Void main()
{
A a;
A *pa;//定义一个基类型指针
B b;
pa=&b;//赋值兼容原则,基类指针可以指向派生类
a.f();//基类对象访问基类成员 f()
b.f();//派生类对象访问类 B的 f()
pa->f();//访问的是基类 A的 f()
b.A::f();//派生类对象访问基类 A的 f()
}
而 C#中在派生类访问基类被覆盖的同名成员时使用 base关键字来限定。C#还可以通过显式类型转
换来访问基类成员,如:((Parent)child).print(),其中 child 是派生类的对象,Parent 是基类名,
那么这个语句就是通过派生类对象访问基类成员。举例如下:
using System;
public class B0
{
public void fb() //基类同名方法
{
Console.WriteLine("B0's fb called!");
}
}
public class B1:B0
{
public new void fb()//派生类同名方法,new表示有意覆盖,若无会产生编译警告
{
base.fb();//相互通信,派生类中访问基类方法
Console.WriteLine("B1's fb called!");
}
}
public class C
{
public static void Main()
{
B0 b0 = new B0();
b0.fb();//访问基类方法
B0 b1 = new B1();//基类型的引用指向派生类
b1.fb();//访问基类方法
B1 b2 = new B1();
b2.fb();//访问派生类方法
((B0)b2).fb();//显式类型转换访问基类方法
Console.ReadLine();
}
}
多态性就是指在程序运行时,执行的虽然是一个调用方法的语句,却可以根据派生类对象的类型不同
完成方法的不同的具体实现。在使用虚函数实现多态时,C++派生类覆盖基类虚函数时函数名前可写
virtual,也可以不写,默认为虚函数,在 C++中,由于基类和派生类的赋值兼容原则,可以定义一个基
类指针或引用指向派生类对象,那么通过该指针或引用访问的还是基类同名成员,除非把基类同名成员定
义成虚函数,那么基类指针或引用指向派生类对象访问的是派生类同名成员。上例代码修改如下:
Class A
{
Public:
Virtual void f(){};//f()定义成虚函数
};
Class B:A
{
Public:
Virtual void f()//派生类 virtual关键字可省略,默认为虚函数
{
2
A::f();//在派生类中访问基类成员 f(),互相通信
}
};
Void main()
{
A a;
a.f();//基类对象访问基类成员 f()
B b;
b.f();//派生类对象访问类 B的 f()
b.A::f();//派生类对象访问基类 A的 f()
A *pa;//定义一个基类型指针
pa=&b;//赋值兼容原则,基类指针可以指向派生类
pa->f();//访问的是派生类 B的 f(),虚函数的作用
}
C#派生类覆盖基类虚函数必须把基类虚函数 virtual 处写成 override,如:基类中虚函数 public
virtual void f()那么派生类写成 public override void f()。上例修改如下:
using System;
public class B0//public可省略,默认为public访问修饰符
{
public virtual void fb() //基类虚方法
{
Console.WriteLine("B0's fb called!");
}
}
public class B1:B0
{
public override void fb()//派生类覆盖虚方法
{
base.fb();//相互通信,派生类中访问基类方法
Console.WriteLine("B1's fb called!");
}
}
public class C
{
public static void Main()
{
B0 b0 = new B0();//基类对象
b0.fb();//访问基类方法
B0 b1 = new B1();//基类型的引用指向派生类对象
b1.fb();//访问派生了类方法
B1 b2 = new B1();//派生类对象
b2.fb();//访问派生类方法
((B0)b2).fb();//显式类型转换访问派生类方法
Console.ReadLine();
}
}
3 C#虚方法和 C++中的虚函数
首先来观察 C++中的一段程序,如下:
#include "iostream.h"
class B0
{
public:
void f() {cout<<"B0.f"<
f();
}
void main()
{
B0 b0;//基类对象
B1 b1;
B2 b2;
b0=b1;//把派生类对象赋给基类对象,赋值兼容原则
b0.f();//输出 B0.f
b1.f();//同名覆盖原则,输出 B1.f
b2.f();//同名覆盖原则,输出 B2.f
B0 *p;//基类型指针
p=&b1;//基类指针指向派生类,赋值兼容原则
fun(p); //因为是基类指针,所以输出 B0.f
p=&b2;
p->f();//因为是基类指针,所以输出 B0.f
}
如果把上例中基类 B0的 f()函数写成虚函数,那么同样的main()运行结果不同,构成多态,修改如下:
class B0
{
public:
virtual void f() {cout<<"B0.f"<f();//因为虚函数构成多态,所以输出 B2.f
}
我们再来观察一段 C#程序,如下:
class B0
{
public void f()
{
Console.WriteLine("B0.f");
}
}
class B1:B0
{
public void f()
{
4
Console.WriteLine("B1.f");
}
}
class B2 : B1
{
public void f()
{
Console.WriteLine("B2.f");
}
}
class Program
{
static void Main(string[] args)
{
B0 b0 = new B0();//基类对象
b0.f();//输出B0.f
B0 b1 = new B1();//隐式类型转换
b1.f();//输出B0.f,和C++中类似。
B2 b2 = new B2();//派生类对象
b2.f();//输出B2.f
Console.ReadLine();
}
}
如果也把基类中的 f()函数写成虚方法,那么子类必须用 override覆盖
虚方法,构成多态,修改程序如下:
class B0
{
public virtual void f()
{
Console.WriteLine("B0.f");
}
}
class B1:B0
{
public override void f()
{
Console.WriteLine("B1.f");
}
}
class B2 : B1
{
public override void f()
{
Console.WriteLine("B2.f");
}
}
class Program
{
static void Main(string[] args)
{
B0 b0 = new B0();//基类对象
b0.f();//输出B0.f
B0 b1 = new B1();//隐式类型转换
b1.f();//输出B1.f,由于是虚方法,和C++中类似。
B2 b2 = new B2();//派生类对象
b2.f();//输出B2.f
Console.ReadLine();
}
}
如果基类方法写成虚方法,可选择使用 override重写该方法,也可以选择使用 new不重写方法。
再写一个程序演示多态,如下:
5
class Employee
{
protected string name;
public Employee() {}
public Employee(string _name)
{
name = _name;
}
public virtual void StartWork()
{
Console.Write(name+"开始工作:");
}
}
class Manager:Employee
{
public Manager(string name):base(name) {}
public override void StartWork()
{
base.StartWork();
Console.WriteLine("分配工作");
}
}
class Saler:Employee
{
public Saler(string name):base(name) {}
public override void StartWork()
{
base.StartWork();
Console.WriteLine("推销产品");
}
}
class Technolgy : Employee
{
public Technolgy(string name) : base(name) { }
public override void StartWork()
{
base.StartWork();
Console.WriteLine("技术开发");
}
}
class Program
{
static void Main(string[] args)
{
Employee[] emp=new Employee[3];
emp[0] = new Manager("张三");
emp[1] = new Saler("李四");
emp[2] = new Technolgy("王五");
foreach(Employee e in emp)
{
e.StartWork();
}
Console.ReadLine();
}
}
运行结果:
张三开始工作:分配工作
李四开始工作:推销产品
王五开始工作:技术开发
6
4 数组
在 C#中,数组实际上是对象。System.Array 是所有数组类型的抽象基类型。提供创建、操作、搜
索和排序数组的方法,因而在公共语言运行库中用作所有数组的基类。声明数组:
int[] a=new int[5];
可以同时初始化:
int[] a=new int[5] {1,2,3,4,5};
或 int[] a={1,2,3,4,5};
举例如下:
int[] a = new int[10] { 12,4,5,23,-5,21,3,0,-12,100};
for (int i = 0; i<10; i++)
{
Console.Write("{0} ",a[i]);
}
Array.Sort(a);//对数组进行排序
Array.Clear(a,0,10); //对数组元素置0
Array.Reverse(a); //对数组进行转置
for (int i = a.GetLowerBound(0); i <=a.GetUpperBound(0); i++)//数组的上下标
{
Console.Write("{0} ", a[i]);
}
5 C#中按值传递和按引用传递
C#中分为值类型变量和引用类型变量,传递值类型参数,可以通过值传递值类型参数,也可以通过
按引用传递值类型参数。
举例按值传递值类型参数如下:
Class A
{//本例没有实现交换数值的功能
static void swap(int x, int y)//按值传递
{
int t;
t = x;
x = y;
y = t;
}
Public statci void Main()
{
int a=3,b=5;
swap(a,b);//只是传递 a,b的副本,不会改变实参值
Console.WriteLine("{0},{1}",a,b);
}
结果:3,5
举例按引用传递值类型参数如下:
Class A
{
static void swap(ref int x,ref int y)//
{//按引用传递,调用函数前必须赋值
int t;
t = x;
x = y;
y = t;
}
Public statci void Main()
{
int a=3,b=5;
swap(ref a,ref b);
//传递的不是 a,b的值,是对 a,b的引用,形参 x,y也不是 int类型,是对 int类型的引用
Console.WriteLine("{0},{1}",a,b);
7
}
结果:5,3
C#中引用类型变量不直接包含其数据,包含的是对数据的引用,引用类型数据也能按值传递和按引
用传递。
举例按值传递引用类型数据如下:
class passingrefbyval
{
static void change(int[] arr)
{
arr[0]=888; // this change affects the original element.
arr = new int[5] {-3, -1, -2, -3, -4}; // this change is local.
console.writeline("inside the method, the first element is: {0}", arr[0]);
}
public static void main()
{
int[] myarray = {1,4,5};
console.writeline("inside main, before calling the method: {0}", myarray [0]);
change(myarray);
console.writeline("inside main, after calling the method: {0}", myarray [0]);
}
}
输出:
inside main, before calling the method: 1
inside the method, the first element is: -3
inside main, after calling the method: 888
在此情况下,myarray 是一个指向数组的引用,将向方法传递指向 myarray 的引用的一个副本。
我们可以这么理解,一开始 myarray 是数组的引用,通过传递,使 arr 也称为数组的引用,那么这时候
myarrayh和 arr都是同一个数组的引用,所以 change方法中 arr[0]=888;语句改变了这个数组的第
一个元素值,但是 arr = new int[5] {-3, -1, -2, -3, -4};语句分配了新的内存空间,使 arr成为新的一个数组的
引用,所以接下来在 change方法中对 arr引用的数组的操作和myarray引用的数组无关,不会影响它
的值,其实在本例中创建了两个数组,一个在Main方法中,一个在 change方法中。
举例按引用传递引用类型数据如下:
本示例除在方法头和调用中使用 ref 关键字以外,其余和上例相同。
class passingrefbyval
{
static void change(ref int[] arr)
{
arr[0]=888;
arr = new int[5] {-3, -1, -2, -3, -4};
console.writeline("inside the method, the first element is: {0}", arr[0]);
}
public static void main()
{
int[] myarray = {1,4,5};
console.writeline("inside main, before calling the method: {0}", myarray [0]);
change(ref myarray);
console.writeline("inside main, after calling the method: {0}", myarray [0]);
}
}
输出:
inside main, before calling the method: 1
inside the method, the first element is: -3
inside main, after calling the method: -3
我们可以这么理解,由于是使用 ref 按引用传递,所以传递是引用 myarray 本身,也可以说 arr 就
是myarray,都是原始数组的引用,在 change方法中,有语句 arr = new int[5] {-3, -1, -2, -3, -4};
8
使得 arr引用重新指向另一个数组,由于 arr就是myarray,所以此时myarray也指向另一个数组,所
以对 arr的操作就是对myarray的操作。
观察下面对于字符数组的交换:
public class C
{
static void swap1(string x, string y)//按值传递
{
string t;
t = x;
x = y;
y = t;
}
static void swap2(ref string x, ref string y)//按引用传递
{
string t;
t = x;
x = y;
y = t;
}
public static void Main()
{
string s1="abc";
string s2="efg";
swap1(s1, s2);
Console.WriteLine("{0},{1}",s1,s2);
swap2(ref s1,ref s2);
Console.WriteLine("{0},{1}",s1,s2);
Console.ReadLine();
}
}
输出:
abc,efg
efg,abc
6 字符串
C++处理字符串,可以使用字符数组、string类或指针来操作。如下:
char c1[]=”hello!”;
char c2[10];
string s1,s2;
s2=c1;
cin>>s1;
cin>>c2;
cout<
本文档为【C#与C++异同】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。