您的位置:首页 > 编程语言 > C#

C#中的virtual和abstract

2016-07-16 14:43 330 查看
问题来源

virtual是实现C++多态的关键性条件:C++使用关键字virtual来修饰类中的方法,被修饰的方法可以在子类中重写,如此便覆盖基类方法,以实现相同的行为却不同的功能;多继承情况下的基类析构函数通常声明为virtual(虚方法),这样做的好处是:确保正确的析构顺序——基类对象的析构晚于子类对象。除此之外,如果基类中至少有一个函数被声明为纯虚函数(virtual void func()=
0;),那么这个基类为抽象基类,如此它便不能实例对象,并且必须在其派生类中对纯虚函数进行实现,而基类只能声明而不能实现,这类似于C#和JAVA语言中的接口interface。我们知道C#是在C++的基础之上删繁留简后形成的一门语言,它保留了C++很多特性,C#中virtual、abstract和interface这三个关键字经常迷惑初学者,它们有很多相似的地方,也有很多不同的地方。

分析

——virtual关键字

虚方法在哪里声明,又在哪里实现?它在基类中的作用有两种情况——1. 在我看来,基类中定义的虚方法(虚方法就是virtual修饰的方法)除了辅助实现多态特性,其实它和普通函数没什么区别。基类声明或基类定义(即实现)的虚方法,其派生类可以重写也可不重写;如果派生类不重写基类虚方法,那么派生类实例访问的虚方法是基类中定义的方法。。。。2. 在基类中定义了虚方法,并且在派生类中使用override重写了该方法(C++中使用virtual关键字表示要重写虚方法),那么派生类的实例调用中,该虚方法使用的是派生类中重写的方法。

——abstract关键字

抽象方法在哪里声明,又在哪里实现?C++有抽象的概念,但是没提供abstract关键字,C++使用纯虚函数来指明基类为抽象类,而C#显示使用abstract关键字来指明基类为抽象类。这两种语言中抽象类的特性是一致的:抽象类不能有实例,抽象类中的抽象方法(C#)和纯虚函数(C++)不能在基类中直接实现,必须在派生类中实现。简单粗暴的讲:C++中基类必须提供至少一个纯虚函数才可称为抽象基类,基类中不可实现它,必须是在子类中实现;C#中abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现。抽象类和C#中的接口interface有着很重要的异同点,这里不再赘述。

代码实例

using System;
using System.Data.SqlClient;

namespace Test
{
public abstract class LogAbstract
{
public abstract void WriteLog(string Title, string Act, string Remark, int LogTypeId, int UserId);

// 下面代码说明virtual和abstract的简单区别
//public abstract void WriteLog(string str) { } // ERROR!-->无法声明主体,应为他被标记为abstract
//public virtual void WriteLog(int i);// 如果不在子类中实现,则ERROR!--->必须声明主体,因为它未被标记为abstract、extern或particle
virtual void WriteLog(int i);// OK--->基类声明子类实现; 或者直接在基类中实现,若子类再实现则是重写该方法
}

public class LogDerived : LogAbstract
{

// 向数据库表中写入日志
public override void WriteLog(string Title, string Act, string Remark, int LogTypeId, int UserId)
{
// 与数据库连接的字符串
string connStr = "server=localhost; uid=sa; pwd=123; database=db_PDRO";
// sql语句
string sql = "INSERT INTO LogTable (LogTitle, LogAction, LogActionRemark, LogTypeId, UserId) VALUES('" + Title + "', '" + Act + "', '" + Remark + "', '" + LogTypeId + "', '" + UserId + "')";

using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open(); // 打开表
SqlCommand comm = new SqlCommand(); // 创建SqlCommand对象
comm.Connection = conn; // 设置comm要使用的SqlConnection对象
comm.CommandText = sql; // 设置要执行的sql语句

try
{
comm.ExecuteNonQuery();
}
catch (SqlException e) {
throw e;
}
}
}

public override void WriteLog(int i) { }
}

class Program
{
static void Main(string[] args)
{
LogDerived log = new LogDerived();
log.WriteLog("testLog1", "test", "log", 1, 1);
log.WriteLog("testLog2", "test", "log", 1, 2);

Console.Write("hello world!");
Console.ReadLine();
}
}
}

写入数据到数据库中,如下图所示:



结语

这篇博客总结性的对virtual和abstract啰啰嗦嗦了好多,这都是它们太具有迷惑性。但希望能从这些啰嗦的文字中提取出主要信息,下面是对它们的简单粗暴的总结,看着下面的条目,请用脑袋思考下,看看自己是不是掌握了它们的特性。

1. virtual方法在基类中可以实现(若未实现,子类必须为其实现),abstract方法在基类中不可实现;而在派生类中,virtual方法可重写可不重写,abstract方法必须重写。

2. 抽象类不可创建实例,只能被继承,由派生类来实例化。

3. C#中有函数被声明为abstract,那么必须显式使用用abstract修饰类名。

4. C#中派生类重写基类的virtual或abstract方法,记得使用override修饰;C++中派生类重写基类的virtual方法,使用virtual修饰。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  abstract virtual C#