关于OOP:一般来说,C语言中的每个抽象函数都是虚拟的吗?

Is every abstract function virtual in C#, in general?

我在研究堆栈溢出问题,抽象函数和虚函数有什么区别?我想知道,在C语言中,是否应该将每个抽象函数都视为一个虚函数,还是一般的虚函数?

对那个问题的回答"你必须推翻/你可以推翻",我有点困惑。我不是一个C程序员,我倾向于认为抽象函数只是一个编译时概念,抽象函数是定义上的虚拟函数,因为您必须至少提供一个,但可以在层次结构的更深处提供多个实现。

虚拟函数也有编译时维度,因为您不能重写非虚拟函数,但它们大多是运行时概念,因为它"只是"根据实际接收器选择正确的方法实现。


对。根据C 3.0规范第10.6.6节:

When an instance method declaration
includes an abstract modifier, that
method is said to be an abstract
method. Although an abstract method is
implicitly also a virtual method, it
cannot have the modifier virtual.


它必须是虚拟的(jon skeet已经提出了规范来证明它是虚拟的),因为,给定了对抽象基类的引用,必须调用具体派生类的实现。例如,考虑到经典的动物层次结构:

1
2
3
4
5
6
7
8
9
10
11
abstract class Animal{
    public abstract void Speak();
}

class Cat : Animal{
    public override void Speak(){Console.WriteLine("meow");}
}

class Dog : Animal{
    public override void Speak(){Console.WriteLine("bark");}
}

如果函数不是虚拟的,那么接受一个Animal对象并调用其Speak方法的函数将不知道要调用哪个实现。

1
2
3
4
static void TalkToAnimal(Animal a){
    Console.WriteLine("Hello, animal.");
    a.Speak();
}

但是请注意,默认情况下,接口实现不是虚拟的。由于接口与类的工作方式不同,因此不需要真正的多态性来查找接口方法的实现。


是的,是的。证据:

1
2
3
4
5
6
7
8
9
10
11
abstract class A {
    public abstract void Foo();
}
class B : A {
    public override void Foo()
    { /* must do */ }
}
class C : B {
    public override void Foo()
    { /* can do */ }
}

对。

An abstract property declaration specifies that the accessors of the property are virtual, but does not provide an actual implementation of the accessors. (MSDN)


我认为你从"C++"的角度来看问题(简洁,避免必要的关键字,保存击键)。

C哲学是代码的意图应该从源代码的读取中清楚,并且编译器应该能够尽可能地验证该意图。

因此,虽然在生成的msil中抽象方法和虚拟方法(或者抽象类和非抽象类之间,或者out参数和ref参数之间)之间几乎没有什么不同,但是额外的关键字确实告诉维护程序员一些事情,并允许编译器对您正在做的事情进行双重检查。