質問はC++のよくある質問からです。
http://www.parashift.com/c++-faq-lite/protected-virtuals.html
パブリックオーバーロード仮想を使用したコード:
class Base {
public:
virtual void f(int x); ← may or may not be pure virtual
virtual void f(double x); ← may or may not be pure virtual
};
Public Overloaded Non-Virtuals Call Protected Non-Overloaded Virtualsイディオムを介してこれを改善する:
class Base {
public:
void f(int x) { f_int(x); } ← non-virtual
void f(double x) { f_dbl(x); } ← non-virtual
protected:
virtual void f_int(int);
virtual void f_dbl(double);
};
著者は言った:
パブリックオーバーロードされた非仮想呼び出し保護された非オーバーロード仮想イディオムの考え方は、パブリックオーバーロードされたメソッドを非仮想に変更し、それらの呼び出しを保護された非オーバーロード仮想にすることです。
しかし、このイディオムがどのようにリスクを改善するかについて著者が言ったことを私は理解していません。
このイディオムは、非表示ルールを適切に管理する複雑さを基本クラス(単数)に詰め込みます。これは、派生クラス(複数形)が多かれ少なかれ自動的に非表示ルールを処理することを意味します。したがって、これらの派生クラスを作成するさまざまな開発者は、派生クラス自体の詳細にほぼ完全に集中できます。微妙でしばしば誤解されている)隠蔽ルール。これにより、派生クラスの作成者が非表示ルールを台無しにする可能性が大幅に減少します。
なぜこれが隠蔽の問題を解決するのですか?私が理解していることから、名前の非表示は、メンバー関数が「仮想」であるかどうかとは関係ありません。'base'の派生クラスが関数f()を書き換えた場合でも、f(int)とf(double)は非表示になりますよね?
このイディオムから私が見ることができるのは、作者が「ベース」仮想f()を非仮想に変更し、イディオムの名前が言ったように、ヘルパー関数f_int()、f_dbl()を「保護された仮想」に配置することだけです。それはまだ何もしませんが、逆に基本クラスのポインタ/参照から動的バインディングの可能性を排除します。このイディオムの真のメリットは何ですか?
アップデート
ケレク、あなたはこれを言っていますか?私はあなたの答えの2番目の段落を完全には理解していません。例を挙げていただけますか?
class base {
public:
virtual void f(int x);
virtual void f(double x);
}
class derived : public base {
public:
virtual int f(int x); // oops, will hide base::f(int x) AND base::f(double x)
}
base *bp = new base();
base *dp = new derived();
bp->f(int i); // ok
dp->f(int i); // surprise!
dp->f(double d); // compile error!
class Base {
public:
void f(int x) { f_int(x); }
void f(double x) { f_dbl(x); }
protected:
virtual void f_int(int);
virtual void f_dbl(double);
};
class derived : public base {
public:
// nothing to override here 'cause f() is non virtual
protected:
// because f_int() and f_dbl are unique names, override or hide f_int() will not affect f_dbl()?
virtual int f_int(int); // oops, will hide base::f(int x), but developer may want this on purpose
// no effect on f_dbl(), which is good
}
base bobj;
derived dobj;
bobj.f(int i); // ok
dobj.f(double d); // ok