クラスのメンバ変数の宣言と定義とインスタンス化について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
GPGA

クラスのメンバ変数の宣言と定義とインスタンス化について

#1

投稿記事 by GPGA » 17年前

お世話になります。
class Hoge {
	int n;
};
 
とした場合、nは変数の定義になると思います。
この n を静的変数にした場合
class Hoge {
	static int n;
};
int Hoge::n;
 
のように、クラス外にnの実態を定義する必要があります。

これらを考えると、静的変数でないメンバ変数を、class内に記述した場合
変数の定義として扱われ、静的メンバ変数をclass内に記述した場合
それは宣言であり、class外でのインスタンス化を定義と考えるべきでしょうか?

それとも、class内に記述した静的変数は定義であり
class外の記述は、インスタンス化しただけであると考えるべきでしょうか?

御津凪

Re:クラスのメンバ変数の宣言と定義とインスタンス化について

#2

投稿記事 by 御津凪 » 17年前

クラス内で静的メンバ変数は宣言として扱われ、
クラス外で定義される、ではないでしょうか。

宣言は存在を表し、
定義はその実体を表す記述を指すのではないでしょうか。

余り自信はありませんが…。

たかぎ

Re:クラスのメンバ変数の宣言と定義とインスタンス化について

#3

投稿記事 by たかぎ » 17年前

> これらを考えると、静的変数でないメンバ変数を、class内に記述した場合
> 変数の定義として扱われ、静的メンバ変数をclass内に記述した場合
> それは宣言であり、class外でのインスタンス化を定義と考えるべきでしょうか?

定義かどうかという意味ではそうですが、インスタンス化という意味では少し違います。

まず、C++では、インスタンス化(この用語も正確とはいえませんが)には二つの意味があります。
一つは、ある型を持つオブジェクトの実体を生成すること。
もう一つは、テンプレートやインライン関数の実体を生成することです。

前者に限った場合でも、
class Hoge {
	int n;
};
の実体が生成されるのは、
Hoge hoge;
とか、
Hoge* ptr = new Hoge;
とした場合です。
単にクラスを定義しただけでは実体まではできません。

逆に、静的データメンバの場合、
class Hoge {
  static const int n = 123;
};
とすれば、実体まで生成されたと考えることもできます。
ただし、ここでいう実体とは、必ずしも記憶域を占有するものではなく、あくまでも定数としての実体です。

GPGA

Re:クラスのメンバ変数の宣言と定義とインスタンス化について

#4

投稿記事 by GPGA » 17年前

ご返答ありがとうございます。

>>御津凪さん
>宣言は存在を表し、
>定義はその実体を表す記述を指すのではないでしょうか。
グローバル変数や通常の関数の考え方ですと、上記のようになるのですが
クラスの場合、宣言は
class Hoge;
定義は
class Hoge {
・・・
};
と記述します。しかし、たかぎさんも書かれていますが
Hogeを定義しただけでは、実態化はされません。

ただ、staticされた変数というのはHogeというスコープでくくられた
グローバル変数であるという解釈もできます。


>>たかぎさん
つまり、class内の記述==宣言、class外の記述==定義と考えていいということでしょうか?


>>御津凪さん
>>たかぎさん
最初の質問のときに説明足らずでしたので、今ここで補足いたします。
最終的に私が知りたい内容は、classのstatic変数の、C++としての在り方です。

static変数を定義==実態化であるルールの下に存在させるか
定義!=実態化であるクラスのルールの下に存在させるかによって
class内部の記述を宣言とするか、定義とするかが決まってくると考えています。

もっとも、static変数は上記の二つと違い、整数型定数以外は必ず、宣言と定義を
必要とするため、そのどちらにも所属しない第3のルールの下に存在させるということも考えています。
これは、関数はプロトタイプ宣言をしなくても使用する方法はありますし、クラスは、宣言するほうが稀ですが
class内の静的変数は、整数型定数以外は必ず、class内とclass外に記述をしなくてはならないということです。

ibis

Re:クラスのメンバ変数の宣言と定義とインスタンス化について

#5

投稿記事 by ibis » 17年前

クラス外の宣言を省いたときにリンカエラーで「未定義の外部参照」とか出ますし、
メンバ関数のプロトタイプ宣言-定義と同じ扱いなのでしょうか。
つまりクラス内の宣言は宣言だけで、クラス外の宣言は定義も兼ねると。

ちなみにBCC55とGCC3.8.1で試したら、外部で宣言しなくてもエラーは(というか警告すら)出ませんでした。
それらのコンパイラではクラス内の宣言が定義として扱われてるのでしょうかねぇ?
それでクラス外の宣言は無視?

たかぎ

Re:クラスのメンバ変数の宣言と定義とインスタンス化について

#6

投稿記事 by たかぎ » 17年前

> つまり、class内の記述==宣言、class外の記述==定義と考えていいということでしょうか?

定義というのは、一定の条件を満たす宣言のことです。
そして、JIS X3014:2003の3.1 宣言及び定義では、次のように規定されています。

  宣言は, 次の場合を除いて, <u>定義</u>(definition)という。
   - 関数本体を指定せずに関数を宣言している場合
   - extern指定子又は《結合指定》を含んでいて, 《初期化子》も《関数本体》も含んでいない場合
   - クラス宣言の中で静的データメンバを宣言している場合
   - 型定義宣言, 《using宣言》又は《using指令》の場合

つまり、クラスの静的データメンバは宣言ですが、非静的データメンバは定義になります。
しかし、定義であることと実体化であることとは別の話です。
例えば、
template <class T> struct A
{
  static int a;
};

template <class T>
int A::a;
とした場合、クラスの外に書いたA::aは定義ですが、実体ができるのはテンプレートが具現化された時点です。

GPGA

Re:クラスのメンバ変数の宣言と定義とインスタンス化について

#7

投稿記事 by GPGA » 17年前

>>ibisさん
手元のVC9.0とBCC5.5.1で試してみましたが、どちらもリンクエラーが出ました。
エラーが出なかったのは、プログラム内部で使用しなかったから、消されたとかないですかね?

>>たかぎさん
>宣言は, 次の場合を除いて, 定義(definition)という。
> - 関数本体を指定せずに関数を宣言している場合
> - extern指定子又は《結合指定》を含んでいて, 《初期化子》も《関数本体》も含んでいない場合
> - クラス宣言の中で静的データメンバを宣言している場合
> - 型定義宣言, 《using宣言》又は《using指令》の場合
なるほど、ありがとうございます。

ibis

Re:クラスのメンバ変数の宣言と定義とインスタンス化について

#8

投稿記事 by ibis » 17年前

>手元のVC9.0とBCC5.5.1で試してみましたが、どちらもリンクエラーが出ました。
>エラーが出なかったのは、プログラム内部で使用しなかったから、消されたとかないですかね?

あー、消されたかもですね。
インスタンスの宣言はしといたんですが、意味のある処理は何もしてないです。

閉鎖

“C言語何でも質問掲示板” へ戻る