实现纯虚函数的必要性是什么

what's the necessity of the implementation of a pure virtual function

本文关键字:必要性 是什么 函数 实现      更新时间:2023-10-16

纯虚拟函数是抽象基类的必备属性。因此,不应该进行任何实现,这是非常直观的理解。但最近我发现,纯虚拟函数仍然可以在以后定义并静态调用(而不是由对象实例调用)。我想不出这样做的原因。如果一个虚拟函数被定义为纯函数,那么实现它的原因是什么?

class A{
public:
    ...
    virtual void interface() = 0; //Pure Virtual functions
    ...
}
void A::interface() //Implementation
{
    cout<<"This the implementation for A interface";
}

我很好奇这背后的逻辑。为什么c++是这样设计的?

有一个"默认"实现可能是有意义的,如果对具体类有用,可以使用它。他们仍然需要覆盖它,但可以非虚拟地调用基类版本:

struct B : A {
    void interface() {
        A::interface(); // call the default implementation
        // and maybe do some B-specific things too
    }
};

我想不出这样做的原因。如果一个虚拟函数被定义为纯函数,那么实现它的原因是什么?

纯虚拟函数的目的是而不是禁止定义。这是为了将类标记为不可实例化。

提供一个定义可能有助于派生类:

struct A
{
   virtual void foo() = 0;
};
void A::foo()
{
   /* some common logic here */
}
struct B : A
{
   virtual void foo() overrides
   {
      bar();
      A::foo();
   }
   void bar();
};
struct C : A
{
   virtual void foo() overrides
   {
      baz();
      A::foo();
   }
   void baz();
};

纯虚拟函数只是意味着该函数必须被所有派生类覆盖——这并不意味着该功能不能/不应该有自己的实现。这种纯虚拟函数实现的两个最明显的例子是:

  • 派生类实现可以调用基类实现
  • 有时你会希望基类是抽象的,但在这种情况下,没有任何方法可以标记为纯virtual,析构函数是最明显的选择,但在这样的析构函数中仍然需要实现

interface()=0表示派生类必须提供实现,因此定义影响派生类,但允许基类实现该方法,以便派生类始终可以调用base::interface()。

您显然完全误解了术语"静态"在本文中的含义。

是的,纯虚拟函数仍然可以有实体,即它们仍然可以被定义

不,您不能在"没有对象实例"的情况下调用这样的函数,正如您似乎错误地认为的那样。带有实体的纯虚拟函数仍然是非静态成员函数。它仍然需要调用一个对象实例。

当有人说可以"静态"调用这样的函数时,这意味着可以直接调用它,而不使用虚拟调度机制。经过虚拟调度的函数调用有时被称为"虚拟调用"或"动态调用",而直接函数调用有时则被称为"静态调用"。在此上下文中,术语"静态"具有完全不同的含义,与静态成员函数没有任何联系。

在C++语言中,直接的非虚拟(即"静态")调用可以通过在调用中指定限定成员名来显式执行。例如,如果类B派生自类A,那么在某些方法B::foo()中,可以使用以下语法

void B::foo() {
  A::interface(); // <- qualified method name
}

它直接调用您提供的CCD_ 5的实现。对于B类型的对象b,可以执行与相同类型的调用

B b;
b.A::interface(); // <- qualified method name

在这两种情况下,调用都是针对特定对象执行的(第一个示例中为*this,第二个示例为b)。

当派生类的析构函数调用基类的析构因子时,几乎同样的事情也会隐式发生,这就是为什么你经常会在纯虚拟析构函数中遇到这种情况(即它们被声明为纯虚拟的,但有一个主体)。