• ベストアンサー

派生クラスから基本クラス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メンバにはアクセスできると思ったのですが、違うのでしょうか。 ご教授お願いします。

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

  • ベストアンサー
回答No.2

C++では、同じクラスであれば、別のオブジェクトのprotectedメンバにアクセスできます。 quad quad::operator=(quad &ob2) { x = ob2.x; y = ob2.y; } は許されます。基底クラスであっても、同じ基底クラスから派生した別のクラスであっても、クラスが違えば、基底クラスでprotectedとされたメンバにはアクセスできません。 ところで、質問のプログラムの意図を満たすために、コンストラクタ quad(coord&ob2):coord(ob2){}; を使うというのはどうでしょうか。

wiles4416
質問者

お礼

>akayoroshiさん 回答ありがとうございます。 試してみたところ、実際にアクセスできました。 >quad(coord &ob2) : coord(ob2){}; コンストラクタということは、オブジェクトの定義時のみcoordオブジェクトを代入(オブジェクトで初期化)ということでよろしいのでしょうか? 違っていたらすみません。実際は、 coord c1, c2; quad q1, q2; q1 = q2 = c1 = c2; のように使いたいので、x, yにアクセスできるcoordクラスの公開メンバを通してやりとりしてみました。 quad &quad::operator=(coord &ob2) { //get_x(), get_y()はcoordクラスの公開メンバ x = ob2.get_x(); y = ob2.get_y(); return *this; } これで一応希望通りに動いたのですが、もし他に何か方法があれば教えてください。よろしくお願いします。

その他の回答 (4)

回答No.5

コンストラクタは型変換にも使えるということです。 たいていのコンパイラは、コンストラクタを呼び出して新しいオブジェクトを作り出すというコードを生成するのではなく、コンストラクタの定義に従ってコンパイル時に型を変換します。

wiles4416
質問者

お礼

なるほど、勉強になりました。 どうもありがとうございました。

回答No.4

#2の回答を寄せたものです。 コンストラクタ quad(const coord& ob) : coord(ob) {} があれば、代入演算子 quad& operator = (const coord &ob) { return *this = quad(ob); } が不要になります。これがなくても、 coord c; quad q; のときに、 q=c; は q=quad(c); と同じことになります。

wiles4416
質問者

お礼

補足説明ありがとうございます。 試してみたら動いたのですが、少し分からない所がありました。 q = c; この部分でコピーコンストラクタquad(const coord &ob) : coord(ob){}が呼び出されていることを確認したのですが、何故呼び出されたのかわかりません。 コピーコンストラクタが呼び出されるのは、 quad q = c; のような初期化の際の代入文や、 q = quad(c); のように明示的に呼び出した場合だけなのではないのでしょうか? お手数ですがよろしくお願いします。

回答No.3

>コンストラクタということは、 初期化子を調べてください。 >方法があれば教えてください。 get_x, get_y で十分だと思いますが、No2さんの提案だとこうなるのでは class quad : public coord { public: quad() {} quad(const coord& ob) : coord(ob) {} quad& operator = (const coord &ob) { return *this = quad(ob); } };

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.1

protectedメンバは、単純に言うと「外から直接参照することを許さない」つまり、今回のような「ob2.x」という記述によるアクセスを許さない宣言です。 派生クラス内でも参照できるというのはあくまでも「自分のオブジェクト」に限った話です。

wiles4416
質問者

お礼

>D-Matsuさん 回答ありがとうございます。 勉強になりました。

関連するQ&A

  • プログラムの出力の説明を教えてください。

    出力が、画像のようになるのですが、最後に基本クラスのoperator=()が呼ばれるのがわからないです。 なぜ、そのようになるのか教えてください。 /* +,-,=をcoordクラスに関してオーバーロードし、 そのcoordをquadの基本クラスとして使用する */ #include <iostream> using namespace std; class coord{ public: int x, y; //座標 coord(int i = 0, int j = 0){ x = i; y = j; } void get_xy(int &i, int &j){ i = x; j = y; } coord operator+(coord ob2); coord operator-(coord ob2); coord operator=(coord ob2); }; //+をcoordクラスに関してオーバーロードする coord coord::operator+(coord ob2) { coord temp; cout << "coord operator+()を使用" << endl; temp.x = x + ob2.x; temp.y = y + ob2.y; return temp; } //-をcoordクラスに関してオーバーロードする coord coord::operator-(coord ob2) { coord temp; cout << "coord operator-()を使用" << endl; temp.x = x - ob2.x; temp.y = y - ob2.y; } //=をcoordクラスに関してオーバーロードする coord coord::operator=(coord ob2) { cout << "coord operator=()を使用" << endl; x = ob2.x; y = ob2.y; return *this; //代入先のオブジェクトを返す } class quad :public coord{ int quadrant; public: quad(){ x = 0; y = 0; quadrant = 0; } quad(int x, int y) :coord(x, y) { if (x >= 0 && y >= 0)quadrant = 1; else if (x<0 && y >= 0)quadrant = 2; else if (x<0 && y<0)quadrant = 3; else quadrant = 4; } void showq() { cout << "象限を示す:" << quadrant << endl; } quad operator=(coord ob2); }; quad quad::operator=(coord ob2) { cout << "quad operator=()を使用" << endl; x = ob2.x; y = ob2.y; if (x >= 0 && y >= 0)quadrant = 1; else if (x<0 && y >= 0)quadrant = 2; else if (x<0 && y<0)quadrant = 3; else quadrant = 4; return *this; } int main() { quad o1(10, 10), o2(15, 3), o3; int x, y; o3 = o1 + o2; //2つのオブジェクトの加算。演算子+()を呼ぶ o3.get_xy(x, y); o3.showq(); cout << "(o1+o2)X:" << x << ",Y:" << y << endl; o3 = o1 - o2; //2つのオブジェクトの減算 o3.get_xy(x, y); o3.showq(); cout << "(o1-o2)X:" << x << ",Y:" << y << endl; o3 = o1; //オブジェクトを代入する o3.get_xy(x, y); o3.showq(); cout << "(o3=o1)X:" << x << ",Y:" << y << endl; return 0; }

  • C++について教えてください。(初心者です)

    現在C++についての学習を進めているのですが、 2項演算子のオーバーロードで理解できないところがありますので、よろしかったらご教授ください。 //+をcoordクラスに対してオーバーロードする #include<iostream> using namespace std; class coord{ int x,y; public: coord() {x=0;y=0;} coord(int i,int j) {x=i;y=j;} void get_xy(int &i,int &j) {i=x;j=y;} coord operator+(coord ob2); }; //+をcoordクラスに対してオーバーロードする coord coord::operator+(coord ob2) { coord temp; temp.x = x + ob2.x; temp.y = y + ob2.y; return temp; } int main() { coord o1(10,10),o2(5,3),o3; int x,y; o3 = o1 + o2; o3.get_xy(x,y); cout << "(o1+o2) X:" << x << ",Y:" << y << endl; return 0; } この文の中で、o3.get_xy(x,y);というコードがありますが、 ここの部分がよくわからないのです。 そもそも、引数としてx,yがありますが、これはprivateメンバを 見に行きなさい。っと言っているのでしょうか? main()の中から直接使っている?? それとも?? すいません。この辺の理解が薄いようなので、2項演算子のオーバーロードとは関係ないかもしれませんが、教えてください。 よろしくお願いします。

  • 派生クラスで,基本クラスのメンバ変数である構造体の型を・・・

    派生クラスで,基本クラスのメンバ変数である構造体の型を戻り値の型とするメンバ関数を作りたいのですがエラーが発生してしまいます. class A{ protected: struct NODE{ char *name; NODE *next; } NODE *node; }; class B : public A{ public: NODE* sort(NODE* fnode); }; NODE* B::sort(NODE* fnode){ ←エラー ~~~~~ return ○○; } 現在このような状態です. よろしくお願いします.

  • 基本クラスのポインタで、派生クラスのメンバ関数を呼び出す方法?

    VC++でプログラミングをしています。 A(基本クラス) B(派生クラス) を作成しました。Bは、Aの特別な場合です。 このとき、基本クラスAのポインタから、派生クラスBにのみあるメンバ関数を呼ぶことはできないのでしょうか? 基本クラスAにも同じ名前の関数があれば、仮想関数をオーバーロードすれば呼び出せるようですが、この関数は、基本クラスには不要なので、できれば使わないメンバ関数を基本クラスに書きたくありません。 (純粋仮想関数という方法もあるようですが、) 操作としましては、 Aのポインタ配列 A* a[100]を作成し 特別な場合のみ派生クラスBのメンバ関数だけを実行させたいのです。 派生クラスにのみあるメンバ関数を、Readとします。 for(i=0;i<100;i++){ if(派生クラスBの場合){ a[i]->Read() } } 現状では、コンパイルエラーで、 関数Readは、aのメンバ関数ではありませんとなってしまいます。 以上よろしくお願いします。

  • 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できるようになるのか…。 非常にお手数ですが、 どなたかご回答いただけませんでしょうか? 長文になりましたが、宜しくお願いいたします。

  • 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++

    文末のコードのように、 基底クラスで、派生クラスのメンバの参照を持つのはまずいでしょうか。 (classではなくstructにしているのは質問上でのpublic:の省略のためだけです) 初期化順序的には、基底クラスの参照先は、 基底クラスのコンストラクタが走る時点で初期化されていないので、 コンストラクタ内で参照に対して何かしようとすると問題になると思っています。 基底クラスのコンストラクタ内で派生クラスメンバの参照に対して何かしなければ、 参照は有効で、派生クラスのコンストラクタ実行後であれば 問題なく動くと思ってよいでしょうか。 struct A { int& m_ref; A(int& ref) : m_ref(ref) { } }; struct B : public A { int m_obj; B() : A(m_obj) { } };

  • C++超初心者質問

    Visual C++ 2008 Express Edition Ver9.0.30729.1 SP を利用し、以下のプログラムを実行するための手順を教えてください。 Visual C++ 6.0では、ファイル>新規作成→ファイルTAB>C++ソースファイルのように、上記の場合はどのように進んだらよいのでしょう? ファイル>新規作成>プロジェクト→Win32 コンソール アプリケーション??? とすると、↓のエラーが出てしまいます。尚、VC2008をインストールしてから何も触っていません。 http://okwave.jp/qa4665322.html ソース #include<iostream> using namespace std; class coord{ int x,y; public: coord(){x=0;y=0;} coord(int i,int j){x=i,y=j;} void get_xy(int &i,int &j){i=x;j=y;} friend coord operator+(coord ob1,int i); friend coord operator+(int i,coord ob1); }; coord operator+(coord ob1,int i){ coord temp; temp.x=ob1.x+i; temp.y=ob1.y+i; return temp; } coord operator+(int i,coord ob1){ coord temp; temp.x=ob1.x+i; temp.y=ob1.y+i; return temp; } int main(){ char c[3]; // 画面固定のため coord o1(10,10); int x,y; o1=o1+10;; o1.get_xy(x,y); cout<<"(o1+10)X:"<<x<<",Y:"<<y<<"\n"; o1=99+o1;; o1.get_xy(x,y); cout<<"(99+o1)X:"<<x<<",Y:"<<y<<"\n"; cout<<"\nエンターで抜けます"<<endl; // 画面固定のため gets(c); return 0; }

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

    PHP初心者というより、 これはプログラム初心者と言うべきでしょうか。 もう1度同じ内容の質問をします。 それだけ物凄く困っています。 どうか手助けをお願い致します。 まず、ソースコードを見て下さい。 <?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"; これが何故エラーになるのか分かりません。 ここで確認ですが、$oはhogeのインスタンスではあるが、fooのサブクラスhogeとは別物である。 この解釈でいいんでしょうか。 どうぞ宜しくお願い致します。

    • ベストアンサー
    • PHP
  • 基本クラスと派生クラスの宣言順序

    C++のクラスの宣言は、基本クラスから先に宣言しないといけないのでしょうか。 例. 次の順で宣言するとエラーになる。 class A : public B { public: private: } calss B { public: private: }

専門家に質問してみよう