因为需要经常切换C++/C#平台编程,一次性解析下这些关键字吧,写多了容易混。。。
首先呢这些关键字不是两个平台都有的,具体如下:
Virtual | Abstract | override | final | Interface | Sealed | |
---|---|---|---|---|---|---|
C# | √ | √ | √ | × | √ | √ |
C++ | √ | × | √ | √ | × | × |
Virtual与override、final、Sealed
C#:
1.virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。 例如,此方法可被任何继承它的类重写。
2.override方法,是在子类中重写父类中的方法,两个函数的函数特征(函数名、参数类型与个数)相同。用于扩展或修改继承的方法、属性、索引器或事件的抽象或虚拟实现。
3.没有final关键字。
4.Sealed关键字应用于某个类时,sealed 修饰符可阻止其他类继承自该类①。 还可以对替代基类中的虚方法或属性的方法或属性使用 sealed 修饰符。 这使你可以允许类派生自你的类并防止它们替代特定虚方法或属性②。功能类似于C++中的final关键字。
virtual+override举例:
public class car
{
public virtual void Weight()
{
Console.WriteLine("输出车重");
}
}
public class truck : car
{
public override void Weight()
{
Console.WriteLine("卡车车重10吨");
}
}
Sealed①举例
class A {}
sealed class B : A {}
class C : B {}//报错
Sealed②举例
class X
{
protected virtual void F() { Console.WriteLine("X.F"); }
protected virtual void F2() { Console.WriteLine("X.F2"); }
}
class Y : X
{
sealed protected override void F() { Console.WriteLine("Y.F"); }
protected override void F2() { Console.WriteLine("Y.F2"); }
}
class Z : Y
{
// 此处试图重写 F 时报错 error CS0239.
protected override void F() { Console.WriteLine("Z.F"); }
protected override void F2() { Console.WriteLine("Z.F2"); }
}
C++:
1.virtual是定义C++中虚函数的关键字,在使用virtual之前,C++对成员函数使用静态联编,而使用virtual,并且在调用函数时是通过指针或引用调用,C++则对成员函数进行动态联编。
2.override关键字可以指定重写基类中的虚函数的函数的成员(C++中的override只有检测防错的功能,与C#不同)。
3.final关键字可以指定不能在派生类中重写的虚函数①。 您还可以使用它指定无法继承的类②。
4.没有Sealed关键字。
举例:
virtual+override
class car
{
public:
virtual void Weight()=0;
};
class truck : car
{
public:
void Weight() override;
};
virtual+final情况①
struct Object{
virtual void fun() = 0;
};
struct Base : public Object {
void fun() final; // 声明为final
};
struct Derived : public Base {
void fun(); // 无法通过编译
};
virtual+final情况②
class Base final
{
};
// 错误,Derive不能从Base派生。
class Derive
: public Base
{
};
Abstract(C#独有)
指示被修改内容的实现已丢失或不完整。 abstract 修饰符可用于类、方法、属性、索引和事件。 在类声明中使用 abstract 修饰符以指示某个类仅旨在作为其他类的基类。 标记为 abstract 的成员,或包含在抽象类中的成员,都必须由派生自抽象类的类来实现。
看起来是不是和Virtual很像,下面是他们的区别:
1.virtual修饰的方法必须有实现(哪怕是仅仅添加一对大括号),而abstract修饰的方法一定不能实现;
2.virtual可以被子类重写,而abstract必须被子类重写;
3.如果类成员被abstract修饰,则该类前必须添加abstract,因为只有抽象类才可以有抽象方法;
4.无法创建abstract类的实例,只能被继承无法实例化,比如: BaseTest2 base2 = new BaseTest2();将出现编译错误:抽象类或接口不能创建实例;
例如:
abstract class TestAbstractSuper
{
public abstract void Init();
}
class TestAbstractSub:TestAbstractSuper
{
public override void Init()
{
Debug.WriteLine("这是子类重写的方法");
}
}
Interface(C#独有)
可使用 interface 关键字定义接口。 接口包含类或结构可以实现的一组相关功能的定义。
例如,使用接口可以在类中包括来自多个源的行为。 该功能在 C# 中十分重要,因为该语言不支持类的多重继承。 此外,如果要模拟结构的继承,也必须使用接口,因为它们无法实际从另一个结构或类继承。
举例:
public interface car
{
void Weight();
}
public class truck : car
{
public override void Weight()
{
Console.WriteLine("卡车车重10吨");
}
}
可以说和前面提到的Abstract很像了,下面是他们的异同:
相同点:
1、都可以被继承;
2、都不能被实例化;
3、都可以包含方法声明;
4、派生类必须实现未实现的方法。
区别:
1、抽象基类可以定义字段、属性、方法实现,接口只能定义属性、索引器、事件、和方法声明,不能包含字段;
2、抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。微软的自定义接口总是后带able字段,证明其是表述一类“我能做。。。”;
3、接口可以被多重实现,抽象类只能被单一继承;
4、抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中;
5、抽象类是从一系列相关对象中抽象出来的概念,因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性;
6、接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;
7、接口可以用于支持回调,而继承并不具备这个特点;
8、抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的;
9、如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法。