web-dev-qa-db-ja.com

C ++純粋仮想関数には本体があります

純粋な仮想関数(= 0を設定した場合)も関数本体を持つことができます。

純粋な仮想関数がまったく呼び出されない場合、関数本体を提供するためにどのような用途がありますか?

58
Vijay

純粋な仮想関数を呼び出せないというあなたの仮定は絶対に間違っています。関数が純粋仮想と宣言されている場合、それは単に、この関数が仮想ディスパッチメカニズムを介して動的にを呼び出せないことを意味します。それでも、このまったく同じ関数は、静的非仮想直接(仮想ディスパッチなし)と簡単に呼び出すことができます。

C++言語では、呼び出しで関数の修飾名が使用された場合、つまり呼び出しで指定された関数名が<class name>::<function name>形式の場合、仮想関数への非仮想呼び出しが実行されます。

例えば

struct S 
{
  virtual void foo() = 0;
};

void S::foo() 
{
  // body for pure virtual function `S::foo`
}

struct D : S 
{
  void foo() 
  {
    S::foo();       
    // Non-virtual call to `S::foo` from derived class

    this->S::foo(); 
    // Alternative syntax to perform the same non-virtual call 
    // to `S::foo` from derived class
  }
};

int main() 
{
  D d;

  d.S::foo(); 
  // Another non-virtual call to `S::foo`
}
87
AnT

「効果的なC++」マイヤーズは、純粋な仮想関数が本体を持つ理由に言及しています。この純粋な仮想関数を実装する派生クラスは、コードのどこかでこの実装を呼び出すことができます。 2つの異なる派生クラスのコードの一部が類似している場合、関数が純粋仮想である必要がある場合でも、階層内で上に移動することは理にかなっています。

here を参照してください。

27

ほとんどの純粋な仮想機能については、あなたは正しいでしょう。ただし、純粋な仮想デストラクタの場合、実際には対応するデストラクタの実装を定義することが重要です。

  • 「純粋な仮想」とは、派生クラスにデストラクタを実装することを要求することです。
  • 基本クラスデストラクタの実装は、派生クラスデストラクタがその後正常に「チェーンアップ」できるようにするためです。
7