[解決済み] 継承:'A'は'B'のアクセス不能なベースである
疑問点
$ cat inheritance.cpp
#include <iostream>
using namespace std;
class A { };
class B : private A { };
int main() {
A* ab = new B;
}
$
$ g++ inheritance.cpp
inheritance.cpp: In function 'int main()':
inheritance.cpp:9: error: 'A' is an inaccessible base of 'B'
$
私はちょうどこのエラーが理解できません。
私が理解しているように、そして
このチュートリアル
が確認します。
private
のメンバがどのように変化するかを変更するだけです。
class B
のメンバが外界からどのように見えるかを変更するだけです。
private指定は、単に
class B
のメンバの可視性を変更するだけではないと思います。
- 継承の際にこのエラーが発生する理由とその意味を教えてください。
- 基本的に、C++ でこのタイプのコードを許可することの何が問題なのでしょうか? まったく無害に見えますが。
どのように解決するのですか?
継承を非公開にするということは、基本的にBがAを(全く)継承していないという事実さえも非公開である、つまり外部からはアクセスできない/見えないということを意味します。
もしそれが許されるならどうなるかという長ったらしい議論は抜きにして、単純な事実として、それは許されません。派生型のオブジェクトを参照するためにベースへのポインターを使用したい場合は、パブリック継承を使用することにほぼ基づいています。
私的継承は ではない に従うことを必ずしも(あるいは通常も)意図していません。 リスコフ置換の原則 . 公的な継承では、派生オブジェクトは基底クラスのオブジェクトに置き換えられると主張し、適切なセマンティクスは は となります。私的継承は ではなく はそう主張しませんが。私的継承が意味する関係の通常の記述は、"is implemented in terms of"です。
public継承は、派生クラスがベースクラスのすべての機能を維持し、さらに追加する可能性があることを意味します。私的継承は、派生クラスがより制限されたインターフェイスを持つものを実装するために一般的なベースクラスを使用するという、多かれ少なかれ反対の意味を持ちます。
例えば、C++標準ライブラリのコンテナがテンプレートではなく継承を使って実装されていると仮定します。現在のシステムで
std::deque
と
std::vector
はコンテナであり
std::stack
はコンテナ・アダプタで、より限定されたインターフェイスを提供します。テンプレートをベースにしているので
std::stack
のどちらかのアダプタとして使用できます。
std::deque
または
std::vector
.
もし、本質的に同じものを継承して提供したいのであれば、おそらく私的継承を使うでしょうから
std::stack
のようなものになるでしょう。
class stack : private vector {
// ...
};
この場合、間違いなく
ではなく
を操作できるようにしたい。
stack
をあたかも
vector
. そうすると、スタックの期待に反する可能性があります (そしておそらくそうなるでしょう) (たとえば、ユーザーは意図したとおりに純粋にスタックのような方法ではなく、途中でアイテムを挿入したり削除したりできます)。私たちは基本的に
vector
をスタックを実装するための便利な方法として使用していますが、もし (たとえば)
stack
をスタンドアローン (基底クラスへの依存なし) で実装するか、あるいは
std::deque
で再実装することもできます。
ではなく
クライアントコードにとって、これは単なるスタックであり、特別な種類の vector (または deque) ではないはずです。
関連
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] C++の継承 - アクセス不能なベース?
-
[解決済み] C#でベースコンストラクタを呼び出す
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] 私的相続、公的相続、保護相続の違いについて
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
-
[解決済み】AngularJSのスコーププロトタイピング/プロトタイピング継承のニュアンスとは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み] 既に.objで定義されている-二重包含はない
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み] ベースクラスの仮想関数をオーバーライドしている場合、その関数を呼び出すことはできますか?