2012-04-20 25 views
1

多態関数を宣言したいときは、基本クラス関数virtualを宣言しなければならないことが分かります。継承クラスのC++仮想関数

class Base 
{ 
public: 
    virtual void f(); 
}; 

私の質問あなたは、「密封された」しているかのように子供が動作することを期待いた場合でも、仮想として継承クラスの関数を宣言する必要がありますか?

class Child : public Base 
{ 
public: 
    void f(); 
}; 
+0

'私は子が継承され、f()が順番にオーバーライドされた仮想が必要であるかどうかを知っています。 これは単なる間違っています。基本クラスの関数が仮想であるため、継承する関数はすべて暗黙的に暗黙指定されています。したがって、 'virtual'をもう一度使う必要はありません。今までにない。 – Jasper

答えて

7

いいえ、関数バーチャルを再宣言する必要はありません。

基底クラスでvirtual機能が自動的に仮想ように、すべてのオーバーライド機能を宣言する:

struct A 
{ 
    void foo();   //not virtual 
}; 
struct B : A 
{ 
    virtual void foo(); //virtual 
} 
struct C : B 
{ 
    void foo();   //virtual 
} 
+1

あなたの例を再編集して、CがBを継承していることを覚えておいてください。 –

+0

@Kevinそれに感謝します。また、AからのB –

0

宣言F()の子仮想としては、子供の定義を読み取るいくつかのいずれかを助けます。これはドキュメンテーションとして便利です。

0

基本クラスのオーバーライドがvirtualとマークされると、他のすべてのオーバーライドは暗黙的にオーバーライドされます。関数にはvirtualとマークする必要はありませんが、私はドキュメンテーションの目的でそうする傾向があります。

子供が「封印されている」ように動作することが予想される場合でも、最後の部分はですか?、あなたがシールクラスにしたい場合は、あなたが実際にそのようシールクラスを作成することにより、C++ 11(これは一般的にC++ 03で完全に実装可能ではなかった)それを行うことができます。

template <typename T> 
class seal { 
    seal() {} 
    friend T; 
}; 

し、それから、あなたの密閉されたクラス(CRTP)継承:

class Child : public Base, virtual seal<Child> { 
// ... 
}; 

をトリックがあるため、仮想継承を使用することで、階層内のほとんどの派生型が(この場合はint型の仮想基本コンストラクタを呼び出す必要があるということですseal<Child>)、そのコンストラクタはp鋳造されたクラスで暴動し、Childからfriend宣言までしか利用できません。

あなたは密封、または他の 完璧シールを提供していない一般的なアプローチを使用していたすべてのクラスの seal型を作成するかなければならないC++では

(それが改ざんすることができる)

関連する問題