C++静的クラスの役割

このQ&Aのポイント
  • C++で静的オブジェクトの役割について理解できない
  • sObjからは静的メンバ関数と静的メンバ変数は呼び出せるが、他のメンバは呼び出せない
  • sObjからメンバ変数(*hoge)を呼び出すことはできない
回答を見る
  • ベストアンサー

C++ 静的クラスの役割が分からない

こんばんは。 C++で静的オブジェクトがなんなのか試しにプログラミングしているんですが どんな役割があるのか試してもよく分かりません。 static class HOGE { public: int *hoge; private: int value[2]; char moji[6]; public: HOGE() { cout << "HOGE\n"; } void MOJI() { strcpy(moji, "MOJI\n"); } void TEST() { cout << "moji = " << moji << endl; } static void staticMOJI() { } }sObj; sObjからは静的メンバ関数と静的メンバ変数は呼び出せるようです。他は呼び出せません。 そのようにするためにstatic宣言をするものなのでしょうか? このsObjからメンバ変数(*hoge)を呼び出すことは無理なんでしょうか?

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

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

ANo.2で, > この場合,どこかにsObjの定義が必要になります。 と書きましたよね。 > エラーをみると外部シンボル ""public: static class TemMem::HOGE TemMem::sObj" (?sObj@TemMem@@2VHOGE@1@A)" は未解決です。 > とでるので定義しないといけないと思います。 ということまでわかっているのですから,ちゃんと定義すればよいです。 どこかの翻訳単位に, TemMem::HOGE TemMem::sObj; の一行を書くだけです。 <無関係な話> staticメンバ変数へのアクセスをインスタンスを使って書くのは混乱の元かと思います。 myClass.sObjではなく,TemMem::sObjと書く方がよいでしょう。 あと,const int &を返すFunc01も,ローカル変数への参照を返すので問題です。 </無関係な話>

DEADSPACE566
質問者

お礼

あと,const int &を返すFunc01も,ローカル変数への参照を返すので問題です。 ローカル変数を参照渡ししても意味ないですからね。 何も考えず、テストプログラムでそれを参照していました。 staticメンバ変数へのアクセスをインスタンスを使って書くのは混乱の元かと思います。 myClass.sObjではなく,TemMem::sObjと書く方がよいでしょう。 静的クラスであることを知らせるためにもそうしてほうがいいですよね。 参考になりました。

DEADSPACE566
質問者

補足

TemMem::HOGE TemMem::sObj; こうやって書くんですね。 ネット使って調べてもなかなか載ってないんですよね。 静的インナークラスの定義って珍しいんですかね。

その他の回答 (4)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

「sObjを定義してください。というエラーがでます。」って自分で書いているくらいだから, 定義すればいい. #2 にも書かれてるよね.

DEADSPACE566
質問者

お礼

ありがとうございます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

「別枠で新たに質問」なんてしなくていいからあなたが「実際に」どう書いたのかを見せてほしい.

DEADSPACE566
質問者

お礼

ありがとうございます。

DEADSPACE566
質問者

補足

そういってくれると当方としては助かります。 class TemMem { public: static int val2; static int count; int val; public: static double math; public: TemMem() : val() {} public: static class HOGE { public: static int Array[2]; int *hoge; private: int value[2]; char moji[6]; public: HOGE() { cout << "HOGE\n"; } void MOJI() { strcpy(moji, "MOJI\n"); } void TEST() { cout << "moji = " << moji << endl; } static void staticMOJI() { } }sObj; double Func01(const double l) { double d = l + M_PI; return d; } const int &Func01() { int d = 0; return d; } HOGE hoge; }; 上記コードがそのクラスです。 このクラスで、 int a = 100; TemMem myclass; myclass.sObj.hoge = &a; ってやるとエラーです。 sObjを定義してください。というエラーがでます。

回答No.2

そもそも,staticなのはクラスではなく変数です。 つまり, static 型 sObj; という形の,型の部分にクラス定義が直接書かれているだけです。 これが名前空間直下 (大域名前空間含む) に書かれているのであれば, sObjのスコープがファイルスコープであることを示すstaticでしょう。 この場合,他のファイルでsObjを直接利用することができません。 また,これがヘッダファイルに書かれていてインクルードされた場合,各ファイルのsObjは別のインスタンスになります。 # C++ならstaticではなく無名名前空間を使った方がよいでしょう。 それに対して,これがクラスの中で書かれているのであれば, sObjがそのクラスの静的なメンバ変数であることを示すstaticになります。 この場合,どこかにsObjの定義が必要になります。

DEADSPACE566
質問者

お礼

名前空間を使用して隠ぺいするという手段も参考になりました。 ありがとうございます。

DEADSPACE566
質問者

補足

それに対して,これがクラスの中で書かれているのであれば, sObjがそのクラスの静的なメンバ変数であることを示すstaticになります。 この場合,どこかにsObjの定義が必要になります。 エラーをみると外部シンボル ""public: static class TemMem::HOGE TemMem::sObj" (?sObj@TemMem@@2VHOGE@1@A)" は未解決です。 とでるので定義しないといけないと思います。

  • honor
  • ベストアンサー率35% (25/71)
回答No.1

int a = 10; sObj.hoge = &a; cout << *sObj.hoge << endl; VC++2010だとこんな風に出来ましたが、呼び出せないとは具体的にどう呼び出せないのでしょうか。

DEADSPACE566
質問者

補足

自分でも試してみたら動きました。 上記のクラスがインナークラスではない場合はメンバ変数は使えるようです。 実はこのクラスを別のクラスのインナークラスとして宣言してあるんです。そちらのほうが動かないんです。ややこしくて申し訳ない。 分かりやすくするために別枠で新たに質問しようと思います。

関連するQ&A

  • 仮想関数でのオーバーライドでの質問

    仮想関数でのオーバーライドでの質問 二つの派生クラスを定義したのですが、一つ目のクラスのメソッドが実行されないで困っています。 下記にソースを載せておきます。 どこが原因でそうなるのかご指摘お願いします。 /* 継承 */ #include <iostream> using namespace std; class Var { private: int value; static Var* re; public: // 静的関数 static bool func() { // 内部で同一の関数を呼び出す re->show(); return true; } virtual show() { cout << "message00" << "moji" << endl; } // 自身のポインタを取得 Var() { re = this; } }; Var* Var::re = NULL; class Msg01 : public Var { private: int value; public: show(void) { cout << "message01" << "moji" << endl; } }; class Msg02 : public Var { private: int value; public: show(void) { cout << "message02" << "moji" << endl; } }; int main() { Msg01 val; Msg02 msva; val.func(); msva.func(); getchar(); return 0; } /------------------------------------------------------/ 実行結果 message02moji message02moji /------------------------------------------------------/ message01mojiが表示されるはずなんですが表示されないでいます。 Msg02を宣言したためこのようになってしまったんでしょうか?

  • C++ クラス概念

    以下の違いがよく理解できていません。 どなたかご教授お願い致します。 (1)クラスのメンバー変数に static を付けた場合と、 メンバーではない変数に static を付けた場合の違い (2)クラスのメンバー関数に static を付けた場合と、 メンバーではない関数に static を付けた場合の違い [プログラム例] class MyClass { public: static int internalCount; static void func(MyClass& a) {/* ... */} }; static int i; static void f(MyClass& a) { /* ... */ }

  • C++の話です。

    C++の話です。 静的メンバ変数としてクラスを宣言した場合、デストラクタが呼ばれていないようなのですが、呼ぶ方法はありませんか? できれば「new」「delete」を使わずできると理想的です。 分かる方教えていただけると助かります。 以下、サンプルコードです。 「デストラクタが呼ばれました」と出力されない上、デバッガを使って試してみましたが、やはり呼ばれていないようです。 #include<iostream> class Test{   public:     ~Test(){       std::cout<<"デストラクタが呼ばれました"<<std::endl;     } }; class A{   private:     static Test T; }; int main(){   A a;   return 0; }

  • 下記、プログラム内の「char *」の役割

    C++初心者です。 縦長になってしまいますが、 『 #include <iostream.h> void show(int); void show(double); void show(char *);   ←左記の記述の使い方 int main(void) { show(1); show(0.25); show("文字列"); return 0; } void show(int x) { cout << x << endl; } void show(double y) { cout << y << endl; } void show(char *z) { cout << z << endl; } 』 のプログラムにおいて、「char *」の使い方がいまいち理解できません。 上記プログラムですとエラーが表示されないのですが、下記のプログラムだとエラーが発生します。 『 #include <iostream.h> void show(int); void show(double); void show(char);   //←---------上記と違う行 int main(void) { show(1); show(0.25); show("文字列"); return 0; } void show(int x) { cout << x << endl; } void show(double y) { cout << y << endl; } void show(char z) {  //←---------上記と違う行 cout << z << endl; } 』 なぜ、ポインタ(*)を付けないといけないのか分かりやすく教えていただけましょうか。

  • Java→C++:オブジェクトの扱いに戸惑ってます

    C++を学び始めた者です。 これまでJavaを中心に開発していました。 オブジェクトの扱い方に関して若干戸惑っております。 下記のようなコードを実行したところ、問題なく動くことを確認しました。 しかし、Javaでは型の宣言はあくまで型を宣言しただけだったのに対し、 C++では宣言を行っただけでコンストラクタが動き、メンバ変数まで使えます。 下記のコードが動き実行結果も下記のようになることからその様に考えました。 これはJavaでいうところの型宣言の時点でC++はオブジェクトが作成されており、 実態が有ると考えて良いのでしょうか? しかし、new演算子はc++にも存在しているはずです。 上記の事を踏まえた上で Hoge hoge; とするのと  Hoge hoge = new Hoge(); とすることの違いを教えて下さい。 何か基本的なところで考えが誤っているのでしょうか? ----------------------------------------- #include "stdafx.h" #include <iostream> using namespace std; class Hoge { public: int hogeValue; Hoge():hogeValue(1000) { std::cout << "Hoge was constructed." << std::endl; PrintMessage(); getchar(); } public: void PrintMessage(){ std::cout << "PrintMessage was constructed. hogeValue = "<<hogeValue << std::endl; getchar(); } }; int main() { std::cout << "main() was called." << std::endl; getchar(); Hoge hoge; hoge.hogeValue=2000; hoge.PrintMessage(); } ---------------------------------------- 実行結果 main() was called. Hoge was constructed. PrintMessage was constructed. hogeValue = 1000 PrintMessage was constructed. hogeValue = 2000

  • char型変数のアドレスを coutで表示するには

    #include <iostream> using namespace std; int main() { bool b; int i; short s; long l; float f; double d; char c; //上で宣言した変数のアドレスを表示 cout << "bool &b " << &b << endl; cout << "int &i " << &i << endl; cout << "short &s " << &s << endl; cout << "long &l " << &l << endl; cout << "float &f " << &f << endl; cout << "double &d " << &d << endl; cout << "char &c " << &c << endl; //「char &c 」とのみ表示される cout << '\n'; //char型のみ printf で再表示 printf("char &c %p\n", &c); //「char &c ********」と表示される return 0; } 上のプログラムを実行すると cout << "char &c " << &c << endl; のところだけ、アドレスが表示されません。 printfを使えば、char型の変数のアドレスも表示されるのですが…。 coutを使ってchar型のアドレスを表示させるにはどうすればいいのでしょうか。 よろしくお願いします。

  • C#での変数スコープ?

    Net 2.0のC#で同一名の変数を使う場合について質問いたします。 以下のHoge1の場合には「 ローカルの変数 'x' をこのスコープで宣言することはできません。これは、'親またはカレント' スコープで別の意味を持つ 'x' の意味が変更されるのを避けるためです。」と怒られます。 一方、Hoge2の場合には怒られません。 Hoge2内でx=1;ではなくint x=1;と再宣言しているにもかかわらず怒られないのは、Hoge1が厳格にスコープ管理している点からみると意外に感じられます。 http://www.atmarkit.co.jp/ait/articles/0210/16/news001_5.html の記述を見ると、この記事が書かれた2002年ごろにはHoge2もNGだったような印象を受けるのですが、変化があったのでしょうか? この辺りの事情に詳しい方がおられましたらよろしく、お願い申し上げます。 class Class1 {    private void Hoge1()    {       int x;       {          int x = 2; // これはNG!。「ローカルの変数 'x' をこのスコープで宣言することはできません。これは、'親またはカレント' スコープで別の意味を持つ 'x' の意味が変更されるのを避けるためです。」と怒られる。       }    }    int x;    private static void Hoge2()    {       int x=1; //これはOK!親にぶらさげた変数が通る。    } }

  • C++のクラスについて

    /*以下のコメントがある行では何故、コンストラクタ(class2::class2)を指定出来ないのですか? デストラクタ(class2::~class2)の場合も問題なくコンパイルが通り、実行できます (http://codepad.org/1oJkxjyZ の23行目) 開発環境 Windows XP SP3 コンパイラ:GCC 実行結果 class1のコンストラクタ class2のコンストラクタ aiueoの実行 class2のデストラクタ class1のデストラクタ */ #include<iostream> class class1; class class2; class class1{ public: class1(); ~class1(); private: class2*pointer; }; class class2{ public: class2(); ~class2(); void aiueo(); }; class1::class1(){ std::cout<<"class1のコンストラクタ"<<std::endl; pointer=new class2(); pointer->aiueo(); //aiueoを~class2に置き換えてもコンパイル出来るが、class2だとエラーが出る } class1::~class1(){ delete pointer; std::cout<<"class1のデストラクタ"<<std::endl; } class2::class2(){ std::cout<<"class2のコンストラクタ"<<std::endl; } class2::~class2(){ std::cout<<"class2のデストラクタ"<<std::endl; } void class2::aiueo(){ std::cout<<"aiueoの実行"<<std::endl; } int main(){ class1 test1; return 0; }

  • C++ 動的確保について

    学校の演習課題で「クラス Array のメンバ変数を以下のように変更して,配列のサイズを実行時に決められるようにしたい.コンストラクタを適切に修正しなさい.配列のサイズはコンストラクタの引数で指定できるようにすること.main 関数内のオブジェクトの宣言部分を適当に変更して動作を確認しなさい.」という課題が出ました。 指示のメンバ変数の変更は、sizeを定数にしていたものを変数にし、arrayを配列からポインタにする点です。 もとのプログラムはI、私がいじったものがIIです。どうにもセグメンテーションフォルトから抜け出せなくて困っています。どのようにしたら題意のプログラムになるのでしょうか? よろしくお願いします。 ここからI~ #include <iostream> using namespace std; class Array{ private: const static int size = 6; int array[size]; public: Array( ); int getSize( ); void put( int index, int data ); int get( int index ); void show( ); }; Array::Array( ) { for ( int i = 0; i < size; i++ ) { array[i] = 0; } } int Array::getSize( ) { return size; } void Array::put( int index, int data ) { array[index] = data; } int Array::get( int index ) { return array[index]; } void Array::show( ) { cout << "| "; for ( int i = 0; i < getSize( ); i++ ) { cout << get(i) << " | "; } cout << endl; } int main( ) { Array array1; array1.put(1, 2); array1.put(4, 1); array1.show( ); return 0; } ~ここまでI ここからII~ #include <iostream> using namespace std; class Array{ private: int size; int *array; public: Array(int s); ~Array(); int getSize(); void put(int index, int data); int get(int index); void show(); }; Array::Array(int s) { size = s; array = new int; for (int i = 0; i < size; i++) { *array = 0; array++; } array -= size; } Array::~Array() { delete[] array; cout << "デストラクタが呼ばれました。配列の要素数分のメモリを開放します." << endl; } int Array::getSize() { return size; } void Array::put(int index, int data) { *(array + index) = data; } int Array::get(int index) { return *(array + index); } void Array::show() { cout << endl << "| "; for (int i = 0; i < getSize(); i++) { cout << get(i) << " | "; } cout << endl; } int main() { int s = 0; cout << "確保するサイズを入力してください:"; cin >> s; Array array1(s); array1.put(1, 2); array1.put(4, 1); array1.show(); return 0; } ~ここまでII

  • 添字演算子

    #include <iostream> class hoge{ private: int a; public: hoge(){ a = 0; } int operator+(int fuga){ a = a + fuga; return a; } int operator[](int fuga){ return 1; } }; int main(){ hoge* p; p = new hoge; std::cout << ((*p) + 5) << std::endl; std::cout << ((*p)[1] ) << std::endl; // 5 // 1 // std::cout << ((*p) [] 1); エラーです。何故ですか? }