• ベストアンサー

C++ protectedにアクセス不可

C++でお聞きしたいことがあります。 初心者ですのでご容赦ください。 //基本クラス class a1 { protected: a1(); }; //派生クラス class a2 :public a1 { protected: a2():a1(){}; //継承先以外から作成されたくない int t; }; class a3 : public a2 //a2を継承 { public: a3(); ~a3(); private: a2* a; //a2のポインタを持つ }; a3::a3() { t = 3; a = new a2; //コンストラクタの中でnew } a3::~a3() { delete a; //終わったらdelete } int main(void) { a3 a; return 0; } というソースでa3はa2を継承しています。 ですのでa2のprotectedメンバtにアクセスできるはず。 ここまではいいのですが、 a2のコンストラクタもa3でアクセスでき無いのでしょうか? a3のコンストラクタでnewしようとすると error C2248: 'a2::a2' : protected メンバ (クラス 'a2' で宣言されている)にアクセスできません。 a2::a2' の宣言を確認してください。 というエラーが発生します。 やりたいのはa2のような基本クラスが6つほどあり、 a2のメンバ変数が多いので コンストラクタの引数で指定されたものだけ コンストラクタないでnewしたいのです。 なぜ、できないのか? どうすればnewできるようになるのか…。 非常にお手数ですが、 どなたかご回答いただけませんでしょうか? 長文になりましたが、宜しくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • neKo_deux
  • ベストアンサー率44% (5541/12319)
回答No.3

> しかしa3はa2をpublicで継承しているのに、 > なぜできないのかが疑問なのです。 今の状態でpublic継承に変更してみて、 a3::a3() { t = 3; a = new a2; //コンストラクタの中でnew の後で、 printf("this→%p, &t→%p, &a→%p, &(a.t)→%p\n",this, &t, a, &(a->t)); などとしてthisとaのアドレスを表示してみると、その時newされたaと自分自身(this)のアドレスが違うのが分かると思います。 自分自身(this)の外側でprotectで宣言されているものにはアクセスできません。

win0000
質問者

お礼

前回回答をいただいたとおり、 friend classにすることにより 解決しました。 ありがとうございました。

その他の回答 (3)

  • txrx
  • ベストアンサー率45% (83/184)
回答No.4

VC6,VC.NET,GCCで試してみました。 どれもコンパイルできませんでした。 試しにa1に別の関数をprotectedで宣言してa3コンストラクタからアクセスすると問題ないようです。 どうやらコンストラクタのみアクセスできないようですね。 私も知りませんでした。 他の方がprotectedではアクセスできないと書かれていますが、コンストラクタ以外なら全てアクセスできます。(なので、他の方は質問の意味を誤解されてるのではないでしょうか?) なぜコンストラクタだけアクセスできないのでしょう? 理由を考えてみましたが思い当たりませんでした。 MSのみでなくGCCもそうなので、おそらく仕様なのでしょう。 残念です。 解決策としては、friend a3をa2で宣言するしかないようですね。

win0000
質問者

お礼

newせずに普通にメンバとしてインスタンスを持たせることは できますので、 #1様が仰っていたとおりなのでしょうね?…。 解決策をご教授していただいてありがとうございました。 friendすることにより 解決いたしました。

  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.2

a3::a3()の中で a2のインスタンスを作成してどないすんの。 何か勘違いしていませんか? コンパイルエラーの意味は、 int main(void) { a2 *a = new a2; } というのが出来ないのと同じ理由ですよ。 派生クラスa3で親クラスのa2のメンバ変数tに アクセスしたいだけならその一文はいらないです。 a3::a3() { t = 3; }

win0000
質問者

補足

質問がわかりづらくて申し訳ありません。 main の中で a2 のインスタンスが 作成できない理由はわかります。 a2のコンストラクタがprotectedですから…。 しかしa3はa2をpublicで継承しているのに、 なぜできないのかが疑問なのです。 別段、t3にアクセスしたいために a2のインスタンスを作成したいわけではないのです。

  • neKo_deux
  • ベストアンサー率44% (5541/12319)
回答No.1

> なぜ、できないのか? a2::a2()はprotectedですので、これを継承したクラスのオブジェクト、インスタンスの中で使えます。 a3::a3() { t = 3; a = new a2; //コンストラクタの中でnew } の処理ですと、aに代入されるa2クラスのインスタンスのアドレスは、a3=a2のアドレスと異なるものです。 アドレスが異なる→置き場所が異なりますから、これは別のオブジェクトという事になりますので、自分自身の中身で無いのでアクセスできないという事になります。 -- > どうすればnewできるようになるのか…。 しばらくコーディングから遠ざかっていたので、適切なクラスの構成が思いつきません。 friendを使うのかな?(自信なし)

win0000
質問者

お礼

う~んと… かなり難しいです。 意味はわかりませんが、 friend関数を使うとよろしいのでしょうか? さっそく調べてみます。 回答ありがとうございました。

関連するQ&A