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

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

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

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

Q&A

解決済

2回答

2183閲覧

privateのメンバ関数の参照方法他が分かりません

Spe3_0624

総合スコア4

C++

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

0グッド

0クリップ

投稿2021/10/12 15:36

privateのメンバ変数の参照方法他が分かりません

学校の課題で、下のプログラムを改変して実行できるようにせよという課題です。

ヘッダファイル(Circle.h)
#include <stdio.h>

class Circle {
private:
int x, y;
int rad;

public:
Circle (); // 関数の内容は記述しない
Circle (int cx, int cy, int r = 10);
void setPosition (int x, int y);
void setRadius (int rad);
int getRadius ();
void draw ();
};

ソースファイル(Circle.cpp)

#include "Circle.h"

Circle::Circle () { // 引数を指定しない構築子
x = y = 0; rad = 10;
}

Circle::Circle (int cx, int cy, int r) { // 引数を指定する構築子
x = cx; y = cy; rad = r;
}

void Circle::setPosition (int x, int y) {
this->x = x; this->y = y; // this->x はメンバ変数の x であり,引数 x とは異なる変数!
}

void Circle::setRadius (int rad) {
this->rad = rad; // this->rad と rad は異なる変数!
}

int Circle::getRadius () {
return rad;
}

void Circle::draw () {
printf ("位置(%d,%d)に半径%dの円を描画\n", x, y, rad);
}

メイン(main.cpp)

#include "Circle.h"

int main () {
int p[2], r;
for (int i = 0; i < 10; i++) {
Circle circ = new Circle (i+10, 2i+10, 15*(i+1)); // 値を代入しながらの生成
p[0] = circ->x; // エラー!
p[1] = circ->y; // エラー!
r = circ->rad; // エラー!
printf("Position = %d, %d, Radius = %d\n", p[0], p[1], r);
circ->draw ();
}
return (1);
}

このまま実行すると以下のようなエラーが出ます

Circle.h: 関数 ‘int main()’ 内:
Circle.h:5:9: エラー: ‘int Circle::x’ は非公開です
int x, y;
^
main.cpp:7:22: エラー: within this context
p[0] = circ->x; // エラー!
^
In file included from main.cpp:1:0:
Circle.h:5:12: エラー: ‘int Circle::y’ は非公開です
int x, y;
^
main.cpp:8:22: エラー: within this context
p[1] = circ->y; // エラー!
^
In file included from main.cpp:1:0:
Circle.h:6:9: エラー: ‘int Circle::rad’ は非公開です
int rad;
^
main.cpp:9:19: エラー: within this context
r = circ->rad; // エラー!
^

課題の要点は、メンバ変数x、yがprivateになっているので、それを参照する関数
void getPosition(int xy[])を作成し、さらにmain.cppが正常に動作するように、変数p[]、rに値を代入できる文に書き換えるというものです。ネットでいろいろ調べて試したのですが、うまくいかなかったので質問した次第です。環境はlinuxです。回答よろしくお願いします。

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

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

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

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

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

fana

2021/10/13 01:58

> 学校の課題 とのことであれば,そこで用いた教科書的な物を見れば秒で解決するような内容であろうと想像します. 故に > ネットでいろいろ調べて とかいう行動に出ること自体が既にずれているように思えます.
guest

回答2

0

そもそも基礎ができていない。
基礎からやりましょう

今回のエラー理由の前に、『オブジェクト指向とは』を学びましょう。

オブジェクト指向、以下OOPは、
データ(= メンバ変数)と処理(= メンバ関数)をひとまとめにしたオブジェクトなるものを中心に見る発想法です。

C言語でファイルの書き込みとかをするときを考えてみましょう。
FILEポインタと処理(ファイルを開くとか)は別々でしたよね。
たまたまそのデータを担当することになっただけです。

でもこの発想だと、データの状態をプログラマが逐一管理しないといけません。

でもデータと処理をひとまとめにして、オブジェクトにするとどうなるでしょうか。

対象データと処理方法はオブジェクトだけが知っている』という状態にできます。

それによって、オブジェクトにデータの管理や処理を任せるということができます。

C++のstd:: fstreamとかを見てもわかるかと思います。

でもメンバ変数をpublicにすると、『オブジェクト外からでもアクセスができてしまう』のです。

ある意味、他人の財布から拝借するようなものです。

なので基本的にはメンバ変数はprivateにして、鍵をかけるのです。
これによって、オブジェクトまたはこれを継承したクラスオブジェクト以外からはアクセスできないようになります。

親の財布は(許可があれば)子どもは使えるが、赤の他人は基本的に使えないのと一緒です。(そりゃ厳密には違うが、イメージとして)

でも、privateなメンバ(メンバ変数とか)は、オブジェクト外からはアクセスできません。
どうしてもアクセスしたいなら、いわゆるgetter/setterを使います。

でもあまりこの方法もおすすめではありません。
だって、『オブジェクトに管理や処理を任せる』ためですから。

なのでできればgetter/setterは使わずに、『処理だけして結果を返す』的にした方が望ましいですね。

ただ、今回はgetter/setterを使ってアクセスしろという前提があるので、getter/setterを使うべきですが。

そして、クラスはそのオブジェクトを定義するだけのものです。

クラスはコンパイラとかに「こういうデータ構造のやつがあるのでよろしくね」と教えてあげるだけです。

C言語でいえばプロトタイプ宣言みたいな感じでしょうか。厳密には違いますが。

クラスは単なる定義なのでオブジェクトを作らないといけません。それがnewとかで生成するあれです。C++の場合はnewを使わなくてもできますけどね。

で、今回のコードを見ると、ある意味、
他人のパスワードつきスマホを取って、『使えねーんだよ!!!ふざけんな!!!』と逆ギレしているようなものです。
そりゃ、使えないでしょ。って感じです。

privateなのでオブジェクト外からはアクセスできません。なのでメンバ関数を介して間接的にアクセスするか、getter/setterを使ってアクセスするしかありません。

それと、もう一つの問題

それを参照する関数void getPosition(int xy[])を作成し…

の部分は、引数が配列の関数ができればできるはずです。

ちなみにここで学びました。

投稿2021/10/13 22:37

編集2021/10/13 22:41
BeatStar

総合スコア4958

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

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

fana

2021/10/14 02:01 編集

これは 何を回答している ものになるのでしょうか? 課題の内容は,「下のプログラムを改変して実行できるようにせよ」とのことですから --- privateなメンバを直に参照しようとして circ->x; // エラー! とかなっているふざけた状態のコードがここにあります.これを適切な形に修正しましょう --- という話なのだと見えます. (この「エラー!」となるコードを質問者自身が書いて「何でエラーなのか?」と首をかしげている状況なのではない) つまり,「そもそもprivateとは何か?」みたいな前提の話を必要としているわけではないでしょう. では一体何が問題点なのか? と言えば, 現状存在している問題とは,単に【自分ではやりたくない】という一点のみでしょう.
fana

2021/10/14 02:21

でも,私も, setPosition (int x, int y) と getPosition(int xy[]) とで引数の具合が全然違うのが嫌ぁぁああああああああああ こんな課題やりたくねぇええええ! …とか感じたので,個人的には「やりたくない」に賛同できる. (他にもnewとか嫌な点はあるけども,とにかくこのgetter書きたくない! 拒否します!)
BeatStar

2021/10/14 02:22

確かにやりたくないですよね。正直。
guest

0

ベストアンサー

このような感じでどうでしょうか?

Circle.h

#include <stdio.h> class Circle { private: int x, y; int rad; public: Circle (); // 関数の内容は記述しない Circle (int cx, int cy, int r = 10); void setPosition (int x, int y); void setRadius (int rad); void getPosition(int xy[]); // <--追加 int getRadius (); void draw (); };

Circle.cpp

Circle::Circle () { // 引数を指定しない構築子 x = y = 0; rad = 10; } Circle::Circle (int cx, int cy, int r) { // 引数を指定する構築子 x = cx; y = cy; rad = r; } void Circle::setPosition (int x, int y) { this->x = x; this->y = y; // this->x はメンバ変数の x であり,引数 x とは異なる変数! } void Circle::setRadius (int rad) { this->rad = rad; // this->rad と rad は異なる変数! } // 追加 void Circle::getPosition(int xy[]) { xy[0] = this->x; xy[1] = this->y; } int Circle::getRadius () { return this->rad; } void Circle::draw () { printf ("位置(%d,%d)に半径%dの円を描画\n", x, y, rad); }

main.cpp

int main() { int p[2], r; for (int i = 0; i < 10; i++) { Circle *circ = new Circle (i+10, 2*i+10, 15*(i+1)); // 値を代入しながらの生成 circ->getPosition(p); r = circ->getRadius(); printf("Position = %d, %d, Radius = %d\n", p[0], p[1], r); circ->draw (); } }

投稿2021/10/12 16:03

編集2021/10/12 18:35
KotaroUetake

総合スコア9

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問