• ベストアンサー

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

  • protectedメソッドが使用できる範囲

    protectedメソッド(もしくはコンストラクタ)はサブクラスからであればアクセスできると覚えていたのですが、以下のような使い方だとサブクラスから見えなくなるようです。 サブクラスでも別パッケージからは参照できないのでしょうか。 ------------------------- package sample.a; import sample.b.*; public class Main2 { public Main2() { } protected Main2(int a){ }     protected void hoge(){ } } -------------------------- package sample.b; public class Main extends Main2{ public void hoge(){ Main2 m2 = new Main2(1);//ここでエラー m2.hoge(); //この使い方もエラー } } -------------------------------

    • ベストアンサー
    • Java
  • 派生クラスから基本クラスprotectedメンバへのアクセスについて

    C++初心者です。 以下のような基本クラスcoordと、その派生クラスquadがあり、quadクラスに関して=演算子をオーバーロードしました。 class coord { protected: int x, y; }; class quad : public coord { public: quad operator=(coord &ob2); }; quad quad::operator=(coord &ob2) { x = ob2.x; y = ob2.y; } するとob2からxにアクセスできないとエラーが出ます。 quadクラスのメンバ関数内なので、基本クラスのprotectedメンバにはアクセスできると思ったのですが、違うのでしょうか。 ご教授お願いします。

  • Pleiades Eclipse で protected なフィールドへのアクセス時

    現在、Pleiades サイトで配布されている、Eclipse3.5(JRE なし版) を利用して開発しています。(http://mergedoc.sourceforge.jp/) その Eclipse において、コンパイルエラーになってほしいのに、赤線が出ず困っています。 たとえば A クラスと B クラスがあった場合に、 class A {  protected int f1; } class B {  public void meth(A a) {   a.f1 = 10;  } } と記述した場合に、f1 へのアクセス(B クラス meth 内)がエラーとなりません。実行時にエラーとなってしまいます。 f1 を private にすると、コンパイルエラーになります。 B クラスは A クラスを継承していません。 これは Eclipse のバグでしょうか、設定で変更できる場合はその設定方法をご教示いただけないでしょうか。 以上、よろしくお願いいたします。

    • ベストアンサー
    • Java
  • C++の話です。

    C++の話です。 静的メンバ変数としてクラスを宣言した場合、デストラクタが呼ばれていないようなのですが、呼ぶ方法はありませんか? できれば「new」「delete」を使わずできると理想的です。 分かる方教えていただけると助かります。 以下、サンプルコードです。 「デストラクタが呼ばれました」と出力されない上、デバッガを使って試してみましたが、やはり呼ばれていないようです。 #include<iostream> class Test{   public:     ~Test(){       std::cout<<"デストラクタが呼ばれました"<<std::endl;     } }; class A{   private:     static Test T; }; int main(){   A a;   return 0; }

  • クラスがメンバーとしてクラスを持つ時の宣言について

    自作クラスMainClassがMyClassというクラスをメンバー変数として持つ場合、宣言時に引数をいくつか持つコンストラクタを呼び出そうとすると構文エラーとなります。 class MyClass { public: MyClass(int, int); } class MainClass { private: MyClass myclass(10,10); } このような宣言はできないのでしょうか。 引数なしのコンストラクタは呼び出せているようです。

  • パッケージ間のアクセスが分かりません。

    インプレスジャパン「JavaSE7 Silver問題集 P13 問5」より (ファイル1) public class Sample{ protected int num = 10; } (ファイル2) package ex5; public class SampleImpl extends Sample{ public static void main(String[] args){ System.out.println(num); } } ファイル2をコンパルしようとすると、 「エラー: シンボルを見つけられません」とメッセージが表示されます。 SampleとSampleImplクラスは別々のパッケージに属していますが、 変数numはprotectedで修飾されているので、アクセス出来るように 思うのですが、どこが間違っているのでしょうか? 解説には「明示的にパッケージ宣言したクラスから、無名パッケージに 属するクラスにアクセスしようとするとコンパイルエラーになります。」と ありますが、無名パッケージもパッケージの一つであり、 かつ、この2つのクラス間には継承関係もあります。 よろしくお願い致します。

    • ベストアンサー
    • Java
  • C++でfriendクラスにしているのにprivateメンバにアクセスできない

    C++でメンバ変数をprivateにして、特定のクラスにだけ公開するようにクラスをfriend指定したのですがprivateメンバにアクセスできませんとエラーが吐かれてしまいます。 先行宣言したりもしてみたのですがどうしても使用できません。 何か心当たりのあるかた教えてください。 class A { friend class B; private: int a; }; class B { public: void test( A *a ) { a->a = 0; } }; コードは違いますがこんな感じのことをしたいのです。 /* コンソールで小さなプログラムでテストしてみると動くのにいざ実際のソースに組み込むと動かないという奇妙な状態です。よろしくお願いします。 */

  • C++ のクラスの定義

    C++の初心者です。 C++のことでお聞きしたいことがあります。 namespace test1{ class A { friend class B; protected: int a; }; } とtest1の下にAクラスを作り namespace test2{ class B { public: test1::A A1; }; } と別のnamespaceにBというクラスを作り、 A1というAのインスタンスを持ちたいのです。 しかし、Aというクラスを先に宣言しているので Bというクラスが解らないらしく friendがうまく働きません。 friend class test2::B としても test2がまだ宣言されていないので、 ????とコンパイルエラーが出ます。 先にtest2::B を宣言してしまうと、 今度はtest1::Aが解らずに エラーが出てしまいます。 こんな場合はどのように書けばよろしいのでしょうか? 環境はwindows2000でVC++ 6.0です。 どうか宜しくお願いいたします。

  • protectedなのにアクセスできないのは何故

    PHP初心者というより、 これはプログラム初心者と言うべきでしょうか。 まず、ソースコードを見て下さい。 <?php //スーパークラスfooの定義 class foo { //xはprotected protected $x = 10; //yはprivate private $y = 10; } //サブクラスhogeの定義 class hoge extends foo { public function getX(){ return $this->x; } public function getY() { return $this->y; } } $o = new hoge(); echo "x = ".$o->getX()."(メソッド経由)\n"; echo "y = ".$o->getY()."(メソッド経由)\n"; echo "y = ".$o->y."(直接参照)\n"; echo "x= ".$o->x."(直接参照)\n"; var_dump($o); ?> これだと echo "x= ".$o->x."(直接参照)\n"; の部分がエラーになるんですよね。 $oはhogeクラスでfooクラスのサブクラスですよね。 なので、 echo "x= ".$o->x."(直接参照)\n"; これが何故エラーになるのか分かりません。 厚かましいとは存じますが、低レベルな質問なんですけど、 オブジェクト指向のプログラムを学ぶ上で基本的な部分なので、 バカにでも分かる回答を宜しくお願い致したいと思う次第です。

    • ベストアンサー
    • PHP
  • 試作クラス使用C++プログラムが動かない原因

    試しに作成した以下のプログラムにビルドエラーが発生し,困っているので質問しました. コンパイラは,「BBB *b」などクラスポインタ変数の部分がエラーと指摘しているのですが(他にも数か所ありますが…),間違っている理由が分からず困ってます. ご回答,よろしくお願い致します. ----------------------------------- #include <iostream> using namespace std; class AAA { public: // コンストラクタ AAA(){ b = new BBB( this ); } // デストラクタ ~AAA(){ delete b; } // メンバ変数 BBB *b; int i; // メンバ関数 void displayB(){ b->displayA(); } }; class BBB { public: // コンストラクタ BBB( AAA *a ){ this->a = a; } // デストラクタ ~BBB(){} // メンバ変数 AAA *a; int j; // メンバ関数 void displayA(){ printf( "%d\n", a->i ); } }; int main() { // 変数の定義 AAA a; // 変数の初期化 a.i = 2; a.b->j = 5; // 出力 printf( "%d\n", a.i ); a.b->displayA(); return 0; } -----------------------------------

専門家に質問してみよう