日期:2012-07-27  浏览次数:20443 次

微软公司给C#(读为C-Sharp)赋予C++某些面向对象的本质,比如模板,但改变了类的创建方法。本文,我将对比C++和C#的类,并着重说明微软在C#中类创建和使用方面的改变。

一、简介
面向对象(OO)编程在应用设计中已经发展二十来年了。程序不再是一系列函数的堆彻(象一些范例那样的程序),而是对象的集合,每个对象都有其独特的属性和方法来与其它对象打交道。

"C"语言系列是面向对象设计发展的最好例子。C++为开发者提供了优秀的面向对象编程工具,程序员可以显式地创建构造函数,拷贝构造函数,重载操作符,使用模板等等。

象C++这样复杂语言的主要问题是程序员要花上好几个月来掌握面向对象设计本质。新程序员必须学会掌握模板,函数重载,当然还要会创建和使用功能良好的类。

微软公司给C#(读为C-Sharp)赋予C++某些面向对象的本质,比如模板,但改变了类的创建方法。本文,我将对比C++和C#的类,并着重说明微软在C#中类创建和使用方面的改变。

本文对象是熟练的C++程序员,通过一些细节来解释C#面向对象的本质。

二、C#的类有了哪些改变?
如你所知,C#是部分基于C++,部分基于Java语法的语言。C#中还有一些细节上的改变,使得它可以用于现代设计。

当你开始用C#建类时就会立即看到这点。让我们通过一个简单的例子开始了解在C++和C#中是如何建类并进行实例化的。

C++版本:
#include <iostream>

class MyClass
{
 public: void doSomething()
 {
  std::cout << "This is some text";
 }
};

void main()
{
 MyClass mc;
 mc.doSomething();
}

C# 版本:
using System;

class MyClass
{
    public void doSomething()
    {
        Console.WriteLine("This is some text");
    }
}

class EntryPoint
{
    public static void Main()
    {
        MyClass mc = new MyClass();
        mc.doSomething();
    }
}

上面的代码中有几个不同之处。
首先,C++用#include包含语句来指明包含文件iostream.h的物理路径。C#则告诉编译器程序将在System命名空间下操作,所有的命名空间和类都属于System命名空间。C#通过命名空间的名字来决定程序的作用范围(本例中只有System一个命名空间),而不用指明物理路径的包含文件方法。
其次,C#的主程序用Main(注意M是大写)。
第三,C++的类声明结束后要在最后的大括号后面用分号结尾。C#则可用可不用,往往都是省略。
第四,你能看到在C#中必须显式地声明方法和成员的作用域。若不加声明,缺省为私有(只有类成员可以访问),这点与C++一样。C#中有5种作用域:
 公有(public):其他类成员也可以访问
 私有(private):只有类成员才能访问
 保护(protected):类成员和继承类成员可以访问
 内部(internal):只有汇编里的成员才能访问(C#的汇编是代码和资源数据的结合,以asmx作文件后缀)
 内部保护(protected internal):类成员和继承类成员可以访问
最后,与Java一样,C#的方法也可以声明为静态(static)的。静态变量的使用在C#和C++是一样的。在C#里,可以这样创建并调用类的静态方法:
using System;

class MyClass
{
 public static void doSomething()
 {
  Console.WriteLine("This is some text");
 }
};

class EntryPoint
{
 public static void Main()
 {
  MyClass.doSomething();
 }
}

注意,这里直接使用类声明而没有创建类的实例。这是为C#语言增加的非常便利的使用方法,可以节省我们的时间和内存。就是说,不要创建类实例,可以直接调用类的方法。

三、用类修饰语限制对类的访问
以前只能对类成员和类方法设定限制,但不能对类实体作限制。C#可以通过声明类修饰语来对类的实例实行限制,如上节提到的作用域。

C++不能对整个类作限制。看一下C++的类声明:
class Car
{
 public:
  Car();
  Car(Car &c);
  virtual ~Car();

 private:
  int numCars;
  Car* previous;
  Car* next;
};

这里有二种访问类型:公有(public)和私有(private)。继承或将类Car实例化后,程序只能继承这些代码,不能作其它变动,如果要作其它变动就不能将其作为基类。

C#对此了改变。可以附加访问修饰语来限制类成员和方法以及类实例的访问权。C#设定8个访问权限:
 公有(public):可以被所有其它的类访问。没有其它限制修饰语,它的公有性质就一直是缺省的。
 私有(private):只有类成员才能访问。
 保护(protected):类成员和继承类成员可以访问。
 内部(internal):只有汇编里的成员才能访问(C#的汇编是代码和资源数据的结合,以asmx作文件后缀)。
 内部保护(protected internal):类成员和继承类成员可以访问。
 密封(sealed):所有继承类都不能访问。无论直接或间接地将它作为基类,C#编译器都会跳错。
 抽象(abstract):与C++的虚(virtual)类或虚方法相似,抽象类不能直接实例化,抽象函数含有函数名。但在作为基类或继承类时可以使用。
 新建(new):用new创建嵌套类,可以隐藏继承方式,告诉编译器创建一个类的新版本。
 
举例来说,如果要创建一个类,并且这个类不能被作为基类或继承,那么就要创建一个密封类:
sealed class Car
{
 public void paintCar()
 {
  // Code to paint car goes here
 }
}

这时如果要创建一个继承类RedCar:
internal class RedCar : Car
{
 // Won't work.
}

C#编译器就会跳错:
error CS0509: 'RedCar' : cannot inherit from sealed class 'Car'  (不能从密封类'Car'继承)。

四、C++和C#中的虚函数
C++和C#都支持虚函数。在下面的C++例子里,有二个类,分别称为Base(基类)和Derived(继承类):

#include <iostream>
using namespace std;

class Base
{
 public:
  void doWork()
  {