Cpp クラス メンバ変数

提供:yonewiki
2022年10月25日 (火) 12:38時点におけるYo-net (トーク | 投稿記録)による版
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)

C++に戻る


本来の表記は「C++(Cpp) クラス メンバ変数」です。この記事に付けられた題名はテンプレート:記事名の制約から不正確なものとなっています。

※このページではC++にのみ存在する機能として、記事タイトルがC++ クラス メンバ変数になっています。

クラス メンバ変数

この記事の前までに項目、クラスアクセス指定子でなんどか使ってきた言葉なので、既になんとなくわかって頂けているとは思うのですが、改めて、この記事でメンバ変数について記述したいと思います。ここに書いてるC++関連の記事はどこから読んでも理解できるよう考慮しているため。繰り返し、繰り返し同じことを説明している場合があります。意外と、どこから読んでもわかるようには出来上がっていないのが、管理人の不徳の致すところです。参考書にはできないWebページによるリファレンスの特徴として、無駄に文章を長くできると言う利点を生かしつつ、リンクや大きな画像による説明が可能であるという点、および、間違えても、こっそり修正して知らんぷりをするという、そういったずるいことができる利点も含めて、いろいろな思惑で作っています。どうせタダで読めてるんですし、管理人の人柄的なものを前面にだしつつ、実験的な試みを取り入れながら、いままでになかったようなC++の解説記事にしていきたいと、かなり崇高な意識でこの記事作成に取り組んでいます。


嘘。


嘘かよっ。でも少し本気。というわけで本題に入りたいと思います。(このへんまで懲りずに読んで頂けている熱心な人がいたら素晴らしいですね。大体の人は、違うページを検索しなおしてるのやもしれません。)このクソみたいなWikiのおかげでプログラムのなんたるかを知ることができましたという感想をもってくれる人を輩出するのがわたしの希望であり、これを糧にあたらしい未来をささえていけたらなんと光栄なことかとおもっております。


つうか、本題にはいれよ。


メンバ変数というのは、クラスの中で宣言した変数のことでして、構造体でも構造体の中で宣言した変数はメンバ変数という呼びました。それがクラスになっただけのことです。


たとえば…以下のようなクラスがあったとしたらで、クラスのメンバ変数について説明します。

MemberVar001.h

#pragma once
class CMemberVar001
{
private:
  int m_nValue;//★メンバ変数
  void mf_Print(void);
  void mf_Print2(void);
protected:
  int mpro_nValue;//★メンバ変数
  void mfpro_Print(void);
  void mfpro_Print2(void);
public:
  int mpub_nValue;//★メンバ変数
  void mfpub_Print(void);
  void mfpub_Print2(void);

  CMemberVar001(void);
  ~CMemberVar001(void);
};

MemberVar001.cpp

#include "stdafx.h"
#include "MemberVar001.h"

void CMemberVar001::mf_Print(void){
  printf("CMemberVar001 プライベート メンバ関数\n");
  printf("mpub_nValue=%d,mpro_nValue=%d,m_nValue=%d\n",mpub_nValue, mpro_nValue, m_nValue);

  printf("\n");
  printf("CMemberVar001 mf_Print関数から呼び出し\n");
  mfpro_Print2();
  mfpub_Print2();
  printf("\n");

}
void CMemberVar001::mfpro_Print(void){
  printf("CMemberVar001 プロテクト  メンバ関数\n");
  printf("mpub_nValue=%d,mpro_nValue=%d,m_nValue=%d\n",mpub_nValue, mpro_nValue, m_nValue);

  printf("\n");
  printf("CMemberVar001 mfpro_Print関数から呼び出し\n");
  mf_Print2();
  mfpub_Print2();
  printf("\n");
}
void CMemberVar001::mfpub_Print(void){
  printf("CMemberVar001 パブリック  メンバ関数\n");
  printf("mpub_nValue=%d,mpro_nValue=%d,m_nValue=%d\n",mpub_nValue, mpro_nValue, m_nValue);

  printf("\n");
  printf("CMemberVar001 mfpub_Print関数から呼び出し\n");
  mf_Print2();
  mfpro_Print2();
  printf("\n");
}
void CMemberVar001::mf_Print2(void){
  printf("★CMemberVar001 プライベート mfpub_Print2関数\n");
}
void CMemberVar001::mfpro_Print2(void){
  printf("★CMemberVar001 プロテクト  mfpub_Print2関数\n");
}
void CMemberVar001::mfpub_Print2(void){
  printf("★CMemberVar001 パブリック  mfpub_Print2関数\n");
}

CMemberVar001::CMemberVar001(void)
{
}


CMemberVar001::~CMemberVar001(void)
{
}

というようなクラスを作って、実際に以下のようなメインプログラムでクラスを動かすと

sample_main.cpp

#include "stdafx.h"
#include "MemberVar001.h"

int _tmain(int argc, _TCHAR* argv[])
{
  CMemberVar001* CMemberVar001_Instance = new CMemberVar001;//★1.ポインタ変数利用による動的なクラス生成

  CMemberVar001_Instance->mpub_nValue = 100;
  CMemberVar001_Instance->mfpub_Print();

  (*CMemberVar001_Instance).mpub_nValue = 110;
  (*CMemberVar001_Instance).mfpub_Print();

  CMemberVar001 CMemberVar001_obj;//★2.通常のクラス変数による動作

  CMemberVar001_obj.mpub_nValue = 200;
  CMemberVar001_obj.mfpub_Print();

  (&CMemberVar001_obj)->mpub_nValue = 210;
  (&CMemberVar001_obj)->mfpub_Print();
  return 0;
}

上記のようにして、メンバ関数やメンバ変数を呼び出すことができます。


★1.の部分ではクラスのポインタ変数を使って動的にクラスを生成しました。実際にメンバ変数を呼び出すときはアロー演算子を使うのがスッキリしますが、ドットを使う選択演算子でも呼び出すことはできます。


★2.の部分では通常のクラス変数を使ってみました。実際にメンバ変数を呼び出すときは選択演算子を使うのがスッキリしますが、アロー演算子でも呼び出すことはできます。


ヘッダファイル内で、メンバ変数として定義した変数にはコメントに★印と共にメンバ変数と明記しておきました。構造体のメンバと変わらないです。しかしながら、アクセス指定子が使われたようにクラスの定義の方法には、これから紹介する様々な技術によって、更にわかり辛いものになっていきますので、冷静に読み解く力が必要になります。


変数に*をつけて中身を参照する演算子や&つけてアドレス演算子を使った場合、変数全体にカッコをつけなければ、演算子の優先度の関係から、メンバ変数の呼び出しに失敗します。


このプログラムの動作結果は以下のとおりとなります。

出力結果

CMemberVar001 パブリック  メンバ関数
mpub_nValue=100,mpro_nValue=-842150451,m_nValue=-842150451

CMemberVar001 mfpub_Print関数から呼び出し
★CMemberVar001 プライベート mfpub_Print2関数
★CMemberVar001 プロテクト  mfpub_Print2関数

CMemberVar001 パブリック  メンバ関数
mpub_nValue=110,mpro_nValue=-842150451,m_nValue=-842150451

CMemberVar001 mfpub_Print関数から呼び出し
★CMemberVar001 プライベート mfpub_Print2関数
★CMemberVar001 プロテクト  mfpub_Print2関数

CMemberVar001 パブリック  メンバ関数
mpub_nValue=200,mpro_nValue=-858993460,m_nValue=-858993460

CMemberVar001 mfpub_Print関数から呼び出し
★CMemberVar001 プライベート mfpub_Print2関数
★CMemberVar001 プロテクト  mfpub_Print2関数

CMemberVar001 パブリック  メンバ関数
mpub_nValue=210,mpro_nValue=-858993460,m_nValue=-858993460

CMemberVar001 mfpub_Print関数から呼び出し
★CMemberVar001 プライベート mfpub_Print2関数
★CMemberVar001 プロテクト  mfpub_Print2関数

_tmain関数からの呼び出しではパブリック(public:)と定義したアクセス指定子の部分のメンバ変数やメンバ関数へしか呼び出しができません。いろいろな方法で4回ほどメンバ変数を呼び出して、変数に値を直接設定したあと、mfpub_Printというメンバ関数を呼び出す処理を繰り返しています。mfpub_Printメンバ関数ではmpub_nValueの値を表示するようにしていますので少しづつ設定した値が変化していることがわかると思います。ポインタをつかったり、そのまま変数にしたりすることで、クラスのメンバ変数の使い方がごっちゃごっちゃしてきますが、どのような方法であったとしても、指定の方法や表記が異なることはあっても、変数を利用することはできるということを理解できれば、よいと思います。


動的に利用したクラスが消滅したり、クラス変数を定義した関数から抜け出したりすると、クラスはもちろん消滅して変数の中身は全部消えてしまいます。クラスが消えた後もデータを利用する場合は、関数から抜け出したりしてクラスが消滅したあとも存続し続けるクラスや、ファイルやあるいはデータベースやその他の参照可能なオブジェクトやメモリ領域あるいは記憶領域にデータを移さなければデータはなくなってしまいます。データを管理するべき場所をどこにするのかを決めないと、ウィンドウズのような、待機状態になりやすいアプリで、ほとんどの処理が割り込みによって支配されるようなアプリケーションではデータを管理しているクラスが消滅するというようなことが発生すれば、うまくデータを参照してプログラムの動作を決めるというあたりまえの動作に支障をきたします。


ウィンドウズにおけるデータ管理手法やクラスの利用手法はC++を学習しただけでは、よい発想にたどり着くことが出来ない人もいて当然です。まだまだC++を学習したばかりでこのあたりの手法が明確に思い描ける人はかなり才能があるといえると思います。


コンソールアプリケーションとウィンドウズアプリケーションとでは、クラスの作り方の発想方法が異なることはあるのかもしれません。詳しいことはウィンドウズアプリの記事を書くときが来たら説明したいと思います。


クラスのメンバ変数に関する説明記事として以上です。


C++に戻る