ポリモーフィック関数を宣言するときは、基本クラスの関数virtualを宣言する必要があることを私は知っています。
class Base
{
public:
virtual void f();
};
私の質問は、Childが「封印された」ように動作することが予想される場合でも、継承するクラス関数を仮想として宣言する必要があるかどうかです。
class Child : public Base
{
public:
void f();
};
ポリモーフィック関数を宣言するときは、基本クラスの関数virtualを宣言する必要があることを私は知っています。
class Base
{
public:
virtual void f();
};
私の質問は、Childが「封印された」ように動作することが予想される場合でも、継承するクラス関数を仮想として宣言する必要があるかどうかです。
class Child : public Base
{
public:
void f();
};
いいえ、関数仮想を再宣言する必要はありません。
基本クラスのvirtual
関数は、すべてのオーバーライド関数を仮想として自動的に宣言します。
struct A
{
void foo(); //not virtual
};
struct B : A
{
virtual void foo(); //virtual
}
struct C : B
{
void foo(); //virtual
}
基本クラスのオーバーライドがマークされるとvirtual
、他のすべてのオーバーライドは暗黙的にマークされます。virtual
私は文書化の目的でマークする傾向があるので、関数にマークを付ける必要はありませんが。
最後の部分の時点で:子供が「封印された」かのように振る舞うことが期待されていても?、クラスを封印したい場合は、次のように封印クラスを作成することで、実際にC ++ 11で実行できます(これはC ++ 03では一般的に完全には実装できませんでした) 。
template <typename T>
class seal {
seal() {}
friend T;
};
そして、そこから封印されたクラスを継承します(CRTP):
class Child : public Base, virtual seal<Child> {
// ...
};
秘訣は、仮想継承を使用するため、階層内で最も派生した型は仮想ベースコンストラクター(この場合は)を呼び出す必要がありますが、そのコンストラクターはテンプレートクラスではプライベートであり、宣言を通じてseal<Child>
のみ使用できます。Child
friend
seal
C ++では、シールするクラスごとに型を作成するか、完全なシールを提供しない一般的なアプローチを使用する必要があります(改ざんされる可能性があります)
Child で f() を virtual として宣言すると、Child の定義を読みやすくなります。資料として重宝します。