質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

STL

STL(Standard Template Library)は、ジェネティックコンテイナー、イテレーター、アルゴリズム、そして関数オブジェクトのC++ライブラリーです。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

3145閲覧

クラスをprivateで継承したい

s8079

総合スコア36

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

STL

STL(Standard Template Library)は、ジェネティックコンテイナー、イテレーター、アルゴリズム、そして関数オブジェクトのC++ライブラリーです。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

2クリップ

投稿2019/10/20 15:07

前提・実現したいこと

基底クラスのデストラクタが仮想関数ではないため,クラスをprivateで継承したいです.
継承ではなくメンバ変数として持つことも考えましたが,基底クラスのメンバ関数をすべて再定義するのは避けたいです.
基底クラスは変更できませんのでご了承ください.
よろしくお願いします.

発生している問題・エラーメッセージ

error C2243: '型キャスト': 'B *' から 'const A &' の変換は存在しますが、アクセスできません。

該当のソースコード

C++

1class A { 2private: 3 int x; 4public: 5 A(const int &n) : x(n) {} 6 int func() { 7 return x; 8 } 9 int func(const A& a) { 10 return x + a.x; 11 } 12}; 13class B : private A { 14public: 15 using A::A; 16 using A::func; 17}; 18int main() { 19 B b(0); 20 b.func(); 21 b.func(b); // error 22 return 0; 23}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2019/10/20 15:15

なぜ普通に継承するのではなくprivateの必要があるんでしょうか。
s8079

2019/10/20 15:23

基底クラスのポインタに派生クラスをnewするのを防ぐためです. A *b = new B(0); // error
y_waiwai

2019/10/20 15:29

なぜそれがダメなんでしょう ムリなことをやろうとしてませんか
guest

回答4

0

「BはAである」と言えない関係を作ったなら,A型の引数にBを渡そうというのが間違いではないでしょうか.
引数にBを受けたいなら,素直に引数の型がBであるメソッドを追加すれば良いのではないでしょうか.

class B : private A { ... public: //例えばこんなのを書く. int func( const B& b ){ return A::func( *this ); } };

投稿2019/10/21 01:24

fana

総合スコア11656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

基底クラスにキャストしてはいけないのであれば、継承をやめて委譲を使ってみてはどうでしょうか。

委譲 - Wikipedia
【第5回】委譲 (1/4):CodeZine(コードジン)

投稿2019/10/20 15:42

編集2019/10/20 15:45
Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

s8079

2019/10/20 15:52

オーバーライドして基底クラスのメンバ関数を呼び出すということでしょうか?
Zuishin

2019/10/20 15:55

オーバーライドは継承の時に使う言葉なので、間違っていると思います。 リンクを二つ貼りましたから、とりあえず両方読んでみてください。
dodox86

2019/10/20 16:09

Zuishinさんの「基底クラスにキャストしてはいけないのであれば」の記述が気になり、私自身が質問の意図を取り違えているかもしれないと思って本回答を避けました。すみませんがこちらに便乗させてください。 乱暴ですが、 > b.func((A&)b); とか > b.func(reinterpret_cast<A&>(b)); でコンパイルと実行は通りました。このようなコーディングを許さない、厳格なコードはどう書いたら良いか?と言う質問だったのでしょうか。>s8079さん
guest

0

やっぱり、私もコンポジション ( メンバ変数として保持すること ) するかなぁ。

継承ではなくメンバ変数として持つことも考えましたが,基底クラスの

それなら、Qtとかそういうライブラリによくある、

C++

1B obj; 2A a = obj.a(); 3bool r = a.func1();

とかみたいにするとか、

C++

1B obj; 2if( b.a()->func1() ) std::cout << "OK" << std::endl;

みたいに、B obj ( 質問者さんが作ろうとしているクラスのオブジェクト ) が持つ A a_; (質問でいう、基底クラス?) のアドレスを a() (いわゆるgetter) で返す。
すると、a_ の値を書き換えることができる。

そういう風に、コンポジションすることもできると思います。

基底クラスのポインタに派生クラスをnewするのを防ぐためです.

それなら単純に、AクラスとBクラスは別物として生成して、Aクラスのオブジェクトを生成させて、初期設定なんかは呼び出し元にさせて、Bクラスのオブジェクトを生成するときにコンストラクタで渡すとか。

[例]

C++

1A a; 2a.setText( "C++ is cool!" ); 3a.setPen(); 4// ここでほかにも初期設定 5B b( a ); // aオブジェクトを渡してB bのメンバ変数等にさせる

投稿2019/10/21 04:21

BeatStar

総合スコア4958

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こんにちは。

BへのポインタをAへのポインタへキャストする(A* a = &b;)ことと、BのインスタンスをAの参照へキャストする(A& a = b;)は同等なので、b.func(b);はできません。

例えば、以下のようにすれば近いことはできます。

C+++

1class A { 2private: 3 int x; 4public: 5 A(const int &n) : x(n) {} 6 int func() { 7 return x; 8 } 9 int func(const A& a) { 10 return x + a.x; 11 } 12}; 13class B : private A { 14public: 15 using A::A; 16 using A::func; 17 A& base() { return *this; } 18}; 19int main() { 20 B b(0); 21 b.func(); 22 b.func(b.base()); // error 23 return 0; 24}

投稿2019/10/20 16:13

編集2019/10/20 16:14
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問