扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
四、C++和C#中的虚函数
C++和C#都支持虚函数。在下面的C++例子里,有二个类,分别称为Base(基类)和Derived(继承类):
#include
using namespace std;
class Base
{
public:
void doWork()
{
cout << "Base class working";
}
protected:
virtual void doWork1() = 0;
};
class Derived : public Base
{
public:
void doWork2()
{
cout << "Derived class working";
}
void doWork1()
{
cout << "Dervied pure virtual function working";
}
};
void main()
{
Derived d;
d.doWork1();
}
基类里有二个函数,一个是doWork,另一个是纯虚函数doWork1。doWork1只能被基类的继承类使用。在继承类(公有地继承于基类)里有一个新函数doWork2,和继承于基类纯虚函数的超越函数doWork1。
在C#里实现同样的功能要更容易些。看下面的C#代码:
using System;
abstract class Base
{ public void doWork()
{ Console.WriteLine("Base class working");
}
public abstract void doWork1();
}
class Derived : Base
{ public void doWork2()
{ Console.WriteLine("Derived class working");
}
public override void doWork1()
{ Console.WriteLine("Dervied pure virtual function working");
}
};
class EntryPoint
{
public static void Main()
{
Derived d = new Derived();
d.doWork1();
}
}
C#将基类定义为抽象类,将doWork1定义为抽象方法。这样就可以获得与上述C++纯虚函数同样的功能。Base类只能作为基类或被含有doWork1超越函数的继承类使用。
继承类在超越抽象函数doWork1时,在函数前面加上超越前缀(override)。C#编译器在发现继承类里的override关键字后,就检查基类的同名函数。只要不是直接显式地调用基类函数,编译器总是使用继承类中的方法。
为了让继承类直接操作基类成员和方法,C# 为基类命名了一个别名base。用这个别名,继承类可以直接引用基类成员和方法。示例如下:
using System;
class first {
public void writeIt()
{ Console.WriteLine("Writing from base class");
}
}
class second : first
{
public second()
{
base.writeIt();
}
}
class EntryPoint
{
public static void Main()
{ second s = new second();
}
}
在上述例子中,有二个类。一个是基类(first),另一个是继承类(second)。当创建second类的实例时,它的构造函数自动调用基类的writeIt方法,用控制台指令Console.WriteLine打印屏幕。由此引出C++和C#中的多态性。
五、C++和C#中的多态性实体的多态性使其具有多种表现形式。在C++和C#中处理多态性是很相像的。看一个简单例子:
C++ 版本:
#include
#include
using namespace std;
class Person
{
public:
Person()
{
classType = "Person";
}
friend void ShowType(Person& p);
private:
string classType;
};
class Manager : public Person
{ public:
Manager()
{classType = "Manager";
}
friend void ShowType(Person& p);
private:
string classType;
};
void ShowType(Person& p)
{ cout << p.classType << endl;
} void main()
{ Person p;
Manager m;
ShowType(p);
ShowType(m); }
C# 版本:
using System;
class Person {
public Person()
{ classType = "Person";
}
public string classType;
}
class Manager : Person
{ public Manager()
{
classType = "Manager";
}
public new string classType;
}
class EntryPoint
{ public static void ShowType(ref Person p)
{ Console.WriteLine(p.classType);
}
public static void Main()
{
Person p = new Person();
Person m = new Manager();
ShowType(ref p);
ShowType(ref m);
}
}
在上面的例子里,有一个基类Person,一个继承于基类的Manager类。在EntryPoint类里,创建了一个静态函数ShowType,其表达为:
public static void ShowType(ref Person p)
注意参数里的ref关键字。ref告诉C#编译器向ShowType函数传递一个参数的引用(reference)。在C#中,如果不用ref关键字,函数的参数传递缺省为值(value)传递,将拷贝一个参数值传递到函数中去。
在C++中的参数引用传递表达为: void ShowType(Person& p)
C++用"&"符号表示参数引用使得程序员新手感到困惑,尤其是那些从VB转过来的人。
在C#的主函数(entry point)里,创建了二个新的Person对象,p和m:
Person p = new Person();
Person m = new Manager();
值得一提是,关键字new在C#和C++中用法是不一样的。在C#里,new只创建一个对象实例。这个对象依然创建在管理堆里,但不返回指向对象的内存地址的指针。在上面的C#例子中,创建了二个Person类对象。第二个对象,m,却是Manager类的对象。它使用Manager的构造函数而不是用Person的构造函数。
将Person类对象和Manager类对象引用到ShowType函数,记住,Manager是Person的继承类,但C#的多态性将其表达为一个Person类:
ShowType(ref p);
ShowType(ref m);
当作用到ShowType函数时,它只处理Person对象。C#告诉它说m是Person继承类的对象,它就将m按Person类处理了。所以用p和m作参数调用ShowType函数后得到的输出为:
Person
Person
[译者注:这样解释多态性有点离谱。这段 C#代码的真正含义在于诠释静态函数的作用,而不是什么多态性。上面一段C++代码则可以看成多态性用法的解释。]
六、结论
在我熟悉C#之前,我用了4年VB和2年C++。我可以负责地说,C#是我用过的语言中最具活力和灵活性并使人愉快的语言,而且它是100%面向对象的。如果你是一个C++程序员,现在想转向电子商务编程或干脆就是想换一种更现代的语言,那么就是C#了。有这么三种原因:
如果会使用C#,你就能创建任何应用:Windows应用,控制台应用,Web应用和Web服务等等。
所有的.NET平台使用的语言都编译成为中间语言(IL),并能按照系统环境进行优化。
非常非常容易将C++转换成C#。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者