オブジェクトの宣言

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アタゴ
記事: 31
登録日時: 6年前

オブジェクトの宣言

#1

投稿記事 by アタゴ » 6年前

いまゲーム作りで初期化で困っているのです。それは宣言の時に自作関数の中で宣言(初期化)したオブジェクトをグローバル変数みたいな扱いができるオブジェクト(ローカルとして宣言しておいて宣言時の関数から抜けても残る)として作ることができるのでしょうか?またこういう場合はグローバル変数と同じように宣言しないといけないのでしょうか?コードが必要なら載せます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: オブジェクトの宣言

#2

投稿記事 by softya(ソフト屋) » 6年前

言語も書かれていないので答え辛いです。
C言語ならstaticにすれば寿命はプログラム存在中です。
なんか、オブジェクトの寿命とスコープを混同されているような質問なので、そこら辺を明確にしてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アタゴ
記事: 31
登録日時: 6年前

Re: オブジェクトの宣言

#3

投稿記事 by アタゴ » 6年前

あ、忘れていました。言語はC++です。staticとはどこで宣言しても宣言後でそのプログラム内ならどこでも使えるという意味でしょうか?

nil
記事: 428
登録日時: 8年前

Re: オブジェクトの宣言

#4

投稿記事 by nil » 6年前

>staticとはどこで宣言しても宣言後でそのプログラム内ならどこでも使えるという意味でしょうか?
いいえ、定義の場所によります。

細かいところを省略して簡単に言いますと、
関数内であればその関数内のみ、
関数外であればそのファイル内のみ、です。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: オブジェクトの宣言

#5

投稿記事 by softya(ソフト屋) » 6年前

アタゴ さんが書きました:あ、忘れていました。言語はC++です。staticとはどこで宣言しても宣言後でそのプログラム内ならどこでも使えるという意味でしょうか?
それはスコープが問題になります。
C++ならばクラス内(大雑把)、グローバル、ファイル内、ローカルなどのスコープに別れますね。
あと、インスタンス生成のタイミングの問題も有るので、そんな簡単には片付かないです。

そもそも、C++でグローバルスコープなのは余り良い設計とは言えないと思います。
オブジェクトの更新は制限されたクラスなのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アタゴ
記事: 31
登録日時: 6年前

Re: オブジェクトの宣言

#6

投稿記事 by アタゴ » 6年前

制限されたクラスとはどう言う意味ですか?
それともし
static class-name A;
とH()内で作ったとするとmain()内でAは使えるのですか?
そもそもグローバルスコープとはどう言う意味ですか?
質問が多く、勉強不足ですみません

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: オブジェクトの宣言

#7

投稿記事 by softya(ソフト屋) » 6年前

制限されたクラスとはどう言う意味ですか?
内部の情報をできるだけカプセル化して、基本的に書き換えられないように更新メソッドを持たないクラスですか?って質問です。
グローバルで問題になるのは、不用意な更新ですので。
それともし
static class-name A;
とH()内で作ったとするとmain()内でAは使えるのですか?
そもそもグローバルスコープとはどう言う意味ですか?
質問が多く、勉強不足ですみません
スコープは、ここを読んでいただきましょうか。
「スコープ - Wikipedia」
http://ja.wikipedia.org/wiki/%E3%82%B9% ... C%E3%83%97

と言うことで関数内のインスタンスは関数内にしか見えません。それはstaticしても同じです。
あと無闇に関数外に持ち出すのは設計セオリーがしっかいしていないとバグになります。

それと関数内で作ったインスタンスは、関数を抜けるときにデストラクトされます。つまり寿命が関数を抜けるまでとなります。
staticにすれば、寿命はプログラム生存内となりますが、グローバルに参照が出来ることが目的ならローカルなインスタンスにする意味が無いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ym114

Re: オブジェクトの宣言

#8

投稿記事 by ym114 » 6年前

static変数の初期化が行われると,二回目以降はその行は無視されます.変数はずっと生きているからです.
この性質がグローバル変数と似ているのでスコープ限定のグローバル変数のように説明されることもあります
しかし,スコープ内で生きているからといってスコープ外から見えるわけではありません.
スコープ内で宣言された変数はどう頑張ってもスコープ外からは見ることができないのです.
ということでstatic変数は忘れてください.

自作関数で初期化して,それを外に持ち出したいときは
1.自作関数(スコープ)の外で宣言された変数に値を代入して初期化する
2.自作関数の中で宣言された変数をreturn で返して(値はコピーされます),関数呼び出し側がそれを受け取る
3.自作関数が仮引数に変数へのポインタ/参照を受け取り,それを初期化する
のいずれかの方法を取るのが一般的だと思います.

1.はグローバル変数を初期化するケースです.簡単ですが誰がいつその変数の値を変えたか全く分からなくなるので良い設計ではありません.
2.と3.するように自作関数を作るべきです.

基本的に関数は機械の部品(モジュール)のようなもので,部品単体で何らかの仕事をするものです.
部品は外部の変数に勝手にアクセスせず,部品の中で仕事を終わらせるべきだとおもいませんか?

(おまけ)
// 2.の初期化方法
Object a = CreateObject();
// 3.の初期化方法
CreateObject(&a);
CreateObject(a);
// 生成方法に幅を持たせたい場合は引数アリの関数を作る
Object a = CreateObject(100,200);

(おまけ2)
static変数のポインタを返すような関数ならば,文字通り"自作関数の中で宣言された変数をグローバル変数のように扱う"ことができます.
これはC++でシングルトン, つまりグローバル変数もどきを作るときに使われるテクニックです.

コード:

int* Function()
{
    static int x = 0;
    return &x; // この値はずっと変わらないのでFunction()の返り値はずっと同じ = グローバル変数のように扱える
}

KORYUOH
記事: 44
登録日時: 7年前

Re: オブジェクトの宣言

#9

投稿記事 by KORYUOH » 6年前

ym114 さんが書きました: (おまけ2)
static変数のポインタを返すような関数ならば,文字通り"自作関数の中で宣言された変数をグローバル変数のように扱う"ことができます.
これはC++でシングルトン, つまりグローバル変数もどきを作るときに使われるテクニックです.

コード:

int* Function()
{
    static int x = 0;
    return &x; // この値はずっと変わらないのでFunction()の返り値はずっと同じ = グローバル変数のように扱える
}
Singletonですがこういう書き方も出来ます。

コード:

int& Function(){
	static int x=0;
	return x;
}
後はC++が新しいものであるならばstd::shared_ptrが使えます。

使い方はこんな感じ

コード:

//C++11でコンパイルして動作確認済み
#include <iostream>
#include <memory>            // std::shared_ptr
#include <string>
//クラス
class A{
public:
 A():mName(""){}
 A(const std::string& name):mName(name){}
 void say(){
     std::cout<<"HELLO,"<<mName<<std::endl;
 }
 private:
 std::string mName;
};
//作る関数
std::shared_ptr<A> Create(const std::string& name){
    return std::make_shared<A>(name);
//もしくは
// return std::shared_ptr<A>(new A(name));
}

int main(void){
    
    std::shared_ptr<A> inst = Create("KORYUOH");
    
    inst->say();
    
    return 0;
}



実行結果

コード:

HELLO,KORYUOH
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: オブジェクトの宣言

#10

投稿記事 by softya(ソフト屋) » 6年前

そもそも、グローバルスコープにする必要性があるのか?って事が一番問題だと思います。
どうしても必要なら、一番安全な設計を検討して、その上でどのテクニックを使うか検討するのが正しい手順かなと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アタゴ
記事: 31
登録日時: 6年前

Re: オブジェクトの宣言

#11

投稿記事 by アタゴ » 6年前

newやdeleatなんかも似たようなことができると聞いたのですがこの二つはstaticとどう違うのですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: オブジェクトの宣言

#12

投稿記事 by softya(ソフト屋) » 6年前

アタゴ さんが書きました:newやdeleatなんかも似たようなことができると聞いたのですがこの二つはstaticとどう違うのですか?
newやdeleteは自分で生存寿命を決めることができます。
あるいは、KORYUOHさんが書いたstd::shared_ptrは更に寿命をクラス任せにしてオブジェクトとが使われなくなったらdeleteするという高度な仕組みです。
この質問もそうなのですが、スコープとは別の生存寿命に関するものなのでスコープの問題は別に存在します。

と言うことで、スコープ問題と生存寿命問題は同一視して考えないでください。
同時に考えないといけないものですが、同じものではありません。

【追記】
「変数の記憶寿命とスコープ」
http://www2.ee.knct.ac.jp/el/E3/E305/lifeandscope.html
まず、これをよく頭に叩きこんでみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: オブジェクトの宣言

#13

投稿記事 by h2so5 » 6年前

http://www2.ee.knct.ac.jp/el/E3/E305/lifeandscope.html
静的記憶寿命を持つ変数の記憶領域がヒープ領域に作られると書いてありますけど、これ嘘じゃないですか?
処理系によってはヒープ領域なのかもしれないですけど。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: オブジェクトの宣言

#14

投稿記事 by softya(ソフト屋) » 6年前

h2so5 さんが書きました:http://www2.ee.knct.ac.jp/el/E3/E305/lifeandscope.html
静的記憶寿命を持つ変数の記憶領域がヒープ領域に作られると書いてありますけど、これ嘘じゃないですか?
処理系によってはヒープ領域なのかもしれないですけど。
あうっ。失礼しました。そんな余分なこと書いてありましたか。よく精査せずすいません。
何処か分かりやすそうな所ご存知ありませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

KORYUOH
記事: 44
登録日時: 7年前

Re: オブジェクトの宣言

#15

投稿記事 by KORYUOH » 6年前

とりあえず基本をまとめるとこんな感じですかね

コード:

int global=0; //プログラムのどこからでも書き換え参照可能、プログラムが終了するまで生きている

static int static_global=0;//プログラムが終わるまで生きているけれどこのファイルの中からしかアクセスできない、逆にこのファイル内からならどこからでもアクセスできる。

void func(){
	int local=0;//この関数内だけ生きていて抜けるときには消える。外からはアクセスできない
	static int val=0;//この関数内からしかアクセスできないが関数を抜けても生きている。プログラムと終了で消える。

	int* pointer = new int(0);//deleteされるまで生きている。deleteされないとバグの原因になる。
	delete pointer; //newされたファイルを消す。newしたら必ず消さないといけない。
	
}
C言語を使うと自分の足を誤って撃ち抜いてしまうことがある。 C++を使えばそのような間違いを犯しにくくなる。しかし、やってしまったときには足全体が無くなる。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: オブジェクトの宣言

#16

投稿記事 by softya(ソフト屋) » 6年前

とりあえず、良い参考サイトもなかったので、「変数の記憶寿命とスコープ」の記憶領域の記述は特定の環境に限定されると補足しておきます。
これが適用されない環境もあるので記憶領域の記述に関しては覚えないでください。[修正]
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アタゴ
記事: 31
登録日時: 6年前

Re: オブジェクトの宣言

#17

投稿記事 by アタゴ » 6年前

詳しく教えていただきありがとうございます。
自分でこのことを参考にいろいろやってい行きたいと思います。

閉鎖

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