理解纯虚拟函数

Understanding pure-virtual functions

本文关键字:函数 虚拟      更新时间:2023-10-16

以下代码编译良好:

struct A
{
    const int a;
    virtual void foo() = 0;
};
struct B : A{ };
void A::foo(){ std::cout << "foo" << std::endl; }

演示

问题是结构体A是一个抽象体,因此我们不能实例化它。但我们可以将它和进行子类化

struct A
{
    const int a;
    virtual void foo() = 0;
};
struct B : A{ };
void A::foo(){ std::cout << "foo" << std::endl; }
int main(int argc, char ** argv)
{
    B b;
    b.foo(); //error: implement pure-virtual
}

演示

仍然不能使用Afoo的实现,我怀疑它永远不会被调用。所以,我不知道这个定义的应用。。。是的,提供虚拟析构函数的定义是有用的,但事实并非如此。

纯虚拟的定义在哪里可以使用?

您可以显式调用它。

struct A
{
    const int a;
    virtual void foo() = 0;
};
struct B : A
{
    void foo();
};
void A::foo()
{
    std::cout << "A::foo" << std::endl;
}
void B::foo()
{
    A::foo(); // here
    std::cout << "B::foo" << std::endl;
}
int main(int argc, char ** argv)
{
    B b;
    b.foo(); // prints A::foo followed by B::foo
}

但是您可以(并且必须)实现(如果B是可实例化的)A的void foo()的重写。该实现可以(但绝对不需要)调用BASE实现:

struct B : public A
{
    virtual void foo() {A::foo();}
};

我已经实现了这个场景,其中我有一个非常简单的"基础"实现,但要求所有叶通过链接回这个通用实现来主动决定是否使用这个基础。

您可以从B中调用它。由于A::foo()是纯虚拟的,B需要定义foo:

struct A {
    virtual void foo() = 0;
};
void A::foo(){ std::cout << "A::foo() ran" << std::endl; }    
struct B : A {
    void foo() {
        A::foo(); // <--
        std::cout << "B::foo() ran" << std::endl;
    }
};
int main(int argc, char ** argv)
{
    B b;
    b.foo();
}

这就是在C++中实现接口的方法。您强制子类实现要实例化的方法,并在该抽象基类上的自己的代码中进行多态操作,将特定实现留给接口的客户端。

就基类中的实现而言,我只能想到两个原因。第一,允许它们不必使用特殊情况下的析构函数。第二,B可以根据A::foo()、IE(默认实现)定义自己的实现。