关于Java:虚拟函数与纯虚函数之间的区别是什么?

What is the difference between a virtual function and a pure virtual function?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
C++ Virtual/Pure Virtual Explained

虚函数和纯虚函数有什么区别?


可以在派生类中重写虚函数。纯虚函数必须在派生类中重写。具体来说,除非至少有一个派生类重写了该虚函数,否则不能用纯虚函数实例化类。


维基百科:

A pure virtual function or pure virtual method is a virtual function that is required to be implemented by a derived class that is not abstract. Classes containing pure virtual methods are termed"abstract;" they cannot be instantiated directly, and a subclass of an abstract class can only be instantiated directly if all inherited pure virtual methods have been implemented by that class or a parent class. Pure virtual methods typically have a declaration (signature) and no definition (implementation).


纯虚函数是一个必须由派生类重新定义的虚函数,因此通常在基类中没有实现(尽管可以提供它,但派生类通过作用域解析运算符调用它;感谢@mark ransom和@toolbox指出它)。

如果一个类有纯虚方法,它就不能被实例化,因此从抽象类(即具有纯虚方法的类)派生的任何类都必须定义这种方法才能被实例化。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <iostream>

using std::cout;
using std::endl;

class BaseClass
{
public:

    // A"normal" virtual function which provides a default implementation
    virtual void OnlyVirtual()
    {
        cout<<"BaseClass::OnlyVirtual"<<endl;
    }

    // A"normal" pure virtual function: must be redefined, no default
    // implementation
    virtual void PureVirtual()=0;

    // A pure virtual function that provides a default implementation that can
    // be called only explicitly via scope-resolution operator
    virtual void PureVirtualWImpl()=0;
};

void BaseClass::PureVirtualWImpl()
{
    cout<<"BaseClass::PureVirtualWImpl"<<endl;
}

class Derived0 : public BaseClass
{
public:
    // Define the pure virtual function
    virtual void PureVirtual()
    {
        cout<<"Derived0::PureVirtual"<<endl;
    }

    // notice that, even if there's an implementation of PureVirtualWImpl in
    // BaseClass, since it's marked as pure, Derived0 cannot still be
    // instantiated
};

class Derived1 : public Derived0
{

public:
    // PureVirtual is already defined by the parent class Derived0

    // I must define also PureVirtualWImpl if I want to instantiate this class
    virtual void PureVirtualWImpl()
    {
        cout<<"Derived1::PureVirtualWImpl"<<endl;
    }
};

class Derived2 : public Derived1
{
public:

    // Obviously I can redefine the"normal" virtual function
    virtual void OnlyVirtual()
    {
        cout<<"Derived2::OnlyVirtual"<<endl;
    }

    // Redefine PureVirtual
    virtual void PureVirtual()
    {
        cout<<"Derived2::PureVirtual"<<endl;
    }

    // Just for fun I can redefine PureVirtualWImpl to call the base normally-
    // unaccessible implementation
    virtual void PureVirtualWImpl()
    {
        BaseClass::PureVirtualWImpl();
    }
};

void TestClass(BaseClass & C)
{
    C.OnlyVirtual();
    C.PureVirtual();
    C.PureVirtualWImpl();
}

int main()
{
    // BaseClass b; // <--- compilation error
    // Derived0 d0; // <--- compilation error
    Derived1 d1;
    Derived2 d2;
    TestClass(d1);
    TestClass(d2);
}

输出:

1
2
3
4
5
6
BaseClass::OnlyVirtual
Derived0::PureVirtual
Derived1::PureVirtualWImpl
Derived2::OnlyVirtual
Derived2::PureVirtual
BaseClass::PureVirtualWImpl