2011-07-22 11 views
5

final virtual functionsをC++で読むことができることはちょっと混乱しています。最初に両方の修飾子を省略するだけの違いは何ですか?C++での最終的な仮想関数0x

+0

は一例では、Base' '場合、考慮初期の基本 'f'メソッドを宣言する別のクラスから継承されます。 –

答えて

10

違いは、それを使用するベースではなく、派生したことです。

class Base { 
    virtual void foo() = 0; 
}; 
class Derived : Base { 
    void foo() {} 
    // Still virtual because it's virtual in base- no way to "un-virtual" it 

    virtual void foo() final {} 
    // Now un-overridable. 
}; 

オーバーライドを防止するものではなく、「それ以上の」オーバーライドを防ぐことを考えてください。

+0

ありがとう!私には明らかではないが、仮想が階層全体を運ぶことは明らかである。 –

1

私は最初、私は同じことを思っていた、C++でvirtualと一緒にfinalキーワードの使用に出くわした:それは継承とオーバーライド可能になりvirtualメソッドを宣言し、メソッドを宣言した場合

finalは、そのメソッドがオーバーライドされることを防ぎます。メソッドを宣言しません。は矛盾を形成しますか?

この質問には現在のaccepted answerが良いと思いますが、私はこれを調べて見つけたものに基づいてもう少し詳しく説明しました。

は、次のクラスを考えてみましょう:

class A { 
    public: 
     void hide_me(); 
     virtual void override_me(); 
     virtual void cant_override_me() final; 
}; 

実現する重要なことは、3つのメソッド宣言がすべて異なっていると異なるものを意味していることです。

最初:

void hide_me(); 

は非仮想であり、従って、定義により、オーバーライドすることはできません。

第三は:

virtual void cant_override_me() final; 

final宣言され、したがって、また定義によって、上書きすることはできません。

違いはけど、それはまたをオーバーライドしている(それはvirtual、であるため)あなたがオーバーライドされるcant_override_me適格として考えることができ、一方、hide_meは非仮想であるから、それをオーバーライドすることは、unapplicableであるということですfinal修飾子のため、が無効になりました。つまり、オーバーライドはvirtualと宣言されていないメソッドには適用されませんが、virtualメソッドに適用されますが、finalと宣言されている場合はオーバーライドできません。

今の子クラスを考えてみましょう。

class B: public A { 
    public: 
     void hide_me(); // this hide's A's definition of "hide_me()"; this is not overriding. 
     void override_me(); // implicit "virtual" 
     //void cant_override_me(); // implicit "virtual"; compilation fails 
}; 

あなたクラスBためhide_me()を再定義することができますが、これはちょうど、したがって、関数名をオーバーロードしたりhidingされます。 BAhide_meメソッドにはA::hide_me()でアクセスできますが、Bという参照を持つ他の人はBと宣言しています。:

B *my_b = new B(); 

my_b->A::hide_me()経由hide_meA年代になりました - 隠された定義にアクセスする必要があります。

cant_override_me()の再定義はBになります。

完全な例として、ここでは何が起こっているのか例示するのに役立つプログラムのわずかな再定義である:

#include <cstdio>  
class A { 
    public: 
     inline void hide_me() { 
      printf("a hide_me\n"); 
     } 
     virtual void override_me(); 
     virtual void cant_override_me() final; 
}; 

class B: public A { 
    public: 
     inline void hide_me() { 
      printf("b hide_me\n"); 
     } 
     void override_me(); 
     inline void foo() { 
      A::hide_me(); 
     } 
     // can't override cant_override_me 
}; 

void A::override_me() { 
    printf("a override_me\n"); 
} 

void A::cant_override_me() { 
    printf("a cant_override_me\n"); 
} 

void B::override_me() { 
    printf("b override_me\n"); 
} 

int main (int argc, char *argv[]) { 
    A *a = new A(); 
    A *ab = new B(); 
    B *b = new B(); 

    a->hide_me(); 
    ab->hide_me(); 
    b->hide_me(); 
    b->A::hide_me(); 

    printf("---\n"); 

    a->override_me(); 
    ab->override_me(); 
    b->override_me(); 
    b->A::override_me(); 
} 

プログラムの出力は

a hide_me 
a hide_me 
b hide_me 
a hide_me 
--- 
a override_me 
b override_me 
b override_me 
a override_me 
関連する問題