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

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

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

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

Q&A

解決済

7回答

5247閲覧

クラスのメンバポインタ(?)について

ristori

総合スコア17

C++

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

0グッド

1クリップ

投稿2015/02/19 14:43

クラスについて質問です

class Product{
char name;
int price;
}
としたときnameと
nameとどどちらがメンバなのでしょうか。

例えばこのクラスのオブジェクトproduct1に対してmain関数内で
char example='a';
product1.*name= example;
としたときに、変数example自体はproduct1のメンバなのでしょうか。それともexampleのポインタのみがメンバですか?

そしてこのように、「ポインタをクラスのメンバ」にするような書き方は一般にするものですか?
そもそもポインタは変数ではないのでメンバという言い方はしないのでしょうか?

質問が多くてすいません。

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

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

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

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

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

guest

回答7

0

product1.*name= example;
は正しくは
*product1.name= example;

C,C++には便利な演算子がありまして、「ポインタ変数がクラスのメンバであり、その中身へとアクセスする場合」には、通常->演算子(アロー演算子)を使います。
exampleを代入する場合には下記のようになります。

product1->name = example;

投稿2015/02/24 06:26

FujinamiYuki

総合スコア16

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

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

ristori

2015/02/24 13:39

なるほど!ありがとうございます。
guest

0

nameと*nameとどどちらがメンバなのでしょうか。

クラスのメンバ(変数)とは、その「変数名」のことを指します。この例ではnameがメンバ(変数)です。

としたときに、変数example自体はproduct1のメンバなのでしょうか。
それともexampleのポインタのみがメンバですか?

メンバ(変数)の前に、「クラス」と「インスタンス」の関係、「型」と「変数」の関係がごっちゃになっているようです。まずは簡単なint型のpriceメンバ変数で考えてみてください。

class Product { /*省略*/ }; Product product1; int val = 100; product1.price = val;
  • クラスProduct型の変数product1には、その値としてクラスProductから作り出したインスタンスが格納されています。
  • int型の変数valには、値100が格納されています。
  • procut1.priceは、変数product1に格納されたProduct型インスタンスの、int型のメンバ変数priceを表します。
  • product.price = val;とすると、変数product1に格納されたProduct型インスタンスの、int型のメンバ変数priceに、値100コピーされて代入されます。
// 質問文から転機したコード char example = 'a'; product1.*name = example;

なお、質問文にあるコードではコンパイル時エラーになります。下記のように*を先頭に書く必要があります。(これでコンパイルは通るようになりますが、別の問題があるため実行時エラーになります。)

// 修正したコード char example = 'a'; *product1.name = example;

そしてこのように、「ポインタをクラスのメンバ」にするような書き方は一般にするものですか?

一般的です。

そもそもポインタは変数ではないのでメンバという言い方はしないのでしょうか?

ポインタは「型」です。「int型の変数」と同じように、「ポインタ型変数」という言い方をします。例えばint *p;は、「int型へのポインタ型(=int *型)の変数p」になります。先の例では、「クラスProductのメンバ変数priceは、char型へのポインタ型(=char *型)のメンバ変数」となります。


正しくは *product1.name= example; と書く必要があり、インスタンスを生成するときにnew、deleteで領域を確保しないとエラーがでてしまう

本質的な問題はproduct1.nameが有効なメモリを指していない、つまりポインタ型のメンバ変数nameを初期化していないことです。「インスタンスを生成するときにnew、deleteで領域を確保」は、初期化のための1つの手段です。(他の方法も考えられます)

*product1.nameはポインタ型変数が指す先を見に行く(参照はがし)操作ですが、product1.nameが有効なメモリ(変数)を指していない状態では、プログラムクラッシュなどの実行時エラーを引きおこしたり、全く無関係なメモリ(変数)に書き込んで値を破壊する不可解なバグの原因となります。

投稿2015/02/19 16:17

編集2015/02/20 06:40
yohhoy

総合スコア6189

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

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

ristori

2015/02/20 04:56

なるほど.... ポインタは「整数型」などと同じように、型であるから、nameはポインタ型のメンバ変数ということですね。詳しい説明ありがとうございます。
guest

0

ベストアンサー

言語仕様として正しいかどうか自信はありませんが、回答してみます。

としたときnameと*nameとどどちらがメンバなのでしょうか。

nameがメンバー変数です。
char *namechar *型の変数と捉えたほうが分かりやすいと思います。

例えばこのクラスのオブジェクトproduct1に対してmain関数内で
char example='a';
product1.*name= example;
としたときに、変数example自体はproduct1のメンバなのでしょうか。それともexampleのポインタのみがメンバですか?

メンバーというのは、クラスに所属している変数と関数のことですので、Productクラスのメンバーはnamepriceだけです。

そしてこのように、「ポインタをクラスのメンバ」にするような書き方は一般にするものですか?

一般的に良く使うと思います。と言っても、C++の場合はstringvectorのようにコンテナーの中にポインターを内包することが多いので、間接的に使うことが多いということになるのでしょうか。

ご質問の内容とは少しずれますが、もし文字列としてchar *を使うのであれば、動的に文字列のメモリーを確保することになります。その場合は、メモリーの割り当てと解放を自前で行う必要があります。解放は、クラスのデストラクタ―で行います。

そもそもポインタは変数ではないのでメンバという言い方はしないのでしょうか?

char *nameは、「char型のポインター」の変数です。
上で書いた通りで、これもメンバー変数です。

参考URL:
C/C++は永久に不滅です! - Part4 誰もがつまずくポインタを完璧理解:ITpro


(追記)

*product1.name= example;*は、ポインターの(アドレスに格納されている先の)値にアクセスする(演算を行う)、という意味なので、*product1.nameがメンバーかどうか、という問いをすることは無いと思います。

C/C++の場合、明示的にメモリーの解放(C++の場合はdeleteで行う)をしないと、すぐにエラーにはならず、メモリーリークという状態となってしまうので、特に注意が必要です。

投稿2015/02/19 15:16

編集2015/02/20 05:41
argius

総合スコア9388

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

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

ristori

2015/02/20 05:00

解答ありがとうございます。 メンバ変数となるのは 「char型のポインター」の変数であるnameだけで、*name(内容はexampleのコピー)はメンバ変数ではない、ということですね。
argius

2015/02/20 05:42

追記しました。
ristori

2015/02/20 13:19

詳しい解答ありがとうございます。ポインタの*は演算子という見方をするということですね
guest

0

様々な方が意見していただいているので補足だけ。

そしてこのように、「ポインタをクラスのメンバ」にするような書き方は一般にするものですか?

一般的な理由をあげると、クラスのメンバ変数にしない場合、外部からアクセス可能になり様々なトラブルの原因となります。(ポインタのアドレスを変更した:newで動的確保した場合deleteできないなど)
ポインタを直接扱える状態にすることはC++の思想から好ましくありません。
複数人での開発を考えると、privateで保護することが望ましいでしょう。

インスタンスを生成するときにnew、deleteで領域を確保しないとエラーがでてしまう

newで動的確保する理由は
0. 値を代入できる領域の確保
0. 入ってくるデータ量が不定(バッファオーバーフロー対策)
0. 必要な分だけの領域を使用する(文字列など1文字から不定)
などが挙げられます。

投稿2015/02/26 13:28

yuu.s

総合スコア24

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

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

ristori

2015/02/26 14:51

なるほどよくわかりました。ありがとうございます
guest

0

exampleをnameへ代入する場合、

  1. nameのメモリー領域を確保。
  2. exampleの内容(この場合、'a')をnameにコピー。
  3. nameを使わなくなったら、メモリーを開放(デストラクタなどで)。

の手順になります。
1.2.を行うことで、exampleの実体が無くなっても(exampleがローカル変数で、サブルーチンから抜けるなどでスコープから外れても)、Productのインスタンスがある限り、nameが値を保持しています。

投稿2015/02/24 13:29

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ristori

2015/02/24 13:42

nameはアドレスだと思うのですがexampleはインスタンスのどこにコピーされますか??
退会済みユーザー

退会済みユーザー

2015/02/24 14:18

例えば、Productクラスは以下のような形になると思います。 nameへは、ゲッター、セッターを通してアクセスします。 exampleの値を代入するためには、セッターを使います。 product1.setName(exmple) セッターの中では、 nameのメモリ領域を確保し、 *name = example を行っています。 class Product { public: // コンストラクタ Product() : name_(0), price_(0) {}; // デストラクタ ~Product() { if (name_) { delete name_; name_ = 0; } }; // name_ のゲッター char name() const { return *name_; }; // name のセッター void setName(char name) { if (name_) { delete name_; name_ = 0; } name_ = new char; *name_ = name; }; private: char* name_; int price_; };
ristori

2015/02/25 14:03

詳しい説明ありがとうございます。
guest

0

この場合のメンバ変数になるのは
「char型のポインタ型」の変数nameであり、その内容(char型の変数)*nameはメンバ変数ではない、と理解致しました。

「メンバ変数nameはcharポインタ型である。」
ここまではあっています。

「その内容(char型の変数)*nameはメンバ変数ではない」
上記についてですが、「*name」はchar型の変数ではありません。
「charポインタ型の変数nameの中身を参照する」という操作です。

ポインタの中身を参照するために変数の前につける""と、変数宣言時の""の部分で混乱してそうですね。

ちなみに、多くの教科書でポインタの宣言は「char name;」というような記載になっていますが、上記のような誤解を招きやすいので「char name;」と宣言することをお勧めします。

投稿2015/02/24 05:41

FujinamiYuki

総合スコア16

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

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

ristori

2015/02/24 13:38

*はcharポインタ型の変数nameの中身を参照する演算子、という解釈でよろしいでしょうか。おっしゃる通り混乱していました。
FujinamiYuki

2015/02/25 00:00

その認識で合ってます。 ここ、混乱しやすいですよね…
guest

0

ポインタをクラスのメンバにすることはいたって普通に行う事です。そうでないとオブジェクト間の関連とか表現できませんから。
ちなみに、ポインタであるメンバにアクセスするときはアスタリスクは先頭に付けます。

lang

1char* example = "abc"; 2product1.name = example; 3char c = *product1.name;

あと、下記はproduct1.nameが指す領域が確保されていないので、実行時エラーになるはずです。。

lang

1char example = ’a’; 2*product1.name = example;

投稿2015/02/19 15:23

shinosan

総合スコア209

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

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

ristori

2015/02/20 04:57

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問