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

时间:2011-01-27 23:33:28

标签: java c++

  

可能重复:
  C++ Virtual/Pure Virtual Explained

虚拟功能与纯虚函数有什么区别?

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:2)

来自Wikipedia

  

纯虚函数或纯虚方法是需要由非抽象的派生类实现的虚函数。包含纯虚方法的类称为“抽象”;它们不能直接实例化,如果所有继承的纯虚方法都已由该类或父类实现,则只能直接实例化抽象类的子类。纯虚方法通常具有声明(签名)而没有定义(实现)。

答案 2 :(得分:0)

纯虚函数是一个必须由派生类重新定义的虚函数,因此通常对它没有基类中的实现(尽管可以提供,由派生类通过范围解析运算符调用;感谢@Mark Ransom和@Toolbox指出它。

如果一个类具有纯虚方法,则无法实例化,因此任何派生自抽象类(=具有纯虚方法的类)的类都是可实例化的,必须实际定义此类方法。

示例:

#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);
}

输出:

BaseClass::OnlyVirtual
Derived0::PureVirtual
Derived1::PureVirtualWImpl
Derived2::OnlyVirtual
Derived2::PureVirtual
BaseClass::PureVirtualWImpl