Sirius X

需要無視の自己満足ブログです。

【C++】staticちゃんの謎①

Category:C/C++, プログラミング入門・学習 Comment:0

eye-catch

Twitterのほうで盛んに発言しまくっているのですが、クラス図作っただけでちょっと満足気になってる私です。。
てへぺろ


クラス図。UML?DFD?Excelちゃんに手伝ってもらいました(^q^)

シーン管理などでデザインパターンを使いましたが、ゲームのプレイヤーキャラクターのステータス管理でもステートパターンを使用しないといけません、っぽいね^^

それはいいのですが、、、
よく分からない事が出てきました😅

static キーワードの謎です。

このキーワード、C言語を学習している時からずっとあったのですが、どうやらC++では意味が少し違うらしくその挙動に悩まされております。

とりあえずコード書いちゃいましょう。

#include <iostream>

class IBase {
private:
    static int value;
public:
    virtual ~IBase() = default;
    void Setter(int val) { value = val; }
    int Getter(void) { return value; }
};

int IBase::value;  // !important


class Bell : public IBase {
public:
    Bell() {}
    ~Bell() {}
    void Printf(void) { std::cout << Getter() << std::endl; }
};

class Muska : public IBase {
public:
    Muska() {}
    ~Muska() {}
    void Printf(void) { std::cout << Getter() << std::endl; }
};

int main()
{
    Bell a;
    Muska b;

    a.Setter(100);
    a.Printf();

    b.Setter(200);
    b.Printf();
    a.Printf();

    return 0;
}

IBase(一応インターフェース的な・・・)クラスの中に独立したメンバを定義し、このクラスをそれぞれBellクラスとMuskaクラス(クラスの名前に意味はありません)が継承しています。

main関数の中でスタック定義したクラスのSetterメソッド(IBaseクラス)を使って値を書き込み、コンソールに出力します。

aから100を入れてaを表示。これで100が表示され、bから200を入れてbを表示。200が表示されるはずですよね。
ここまではいいです。

問題はbの表示直後のa表示です。

以下出力結果をご覧ください。

なんだこりゃ??

100、200…200?
え?😓100だろ?最後。。。

と思いきや、staticで宣言された変数は共有されている変数らしく、Bellクラス、Muskaクラスどこを経由しても同じメモリアドレスに書き込むようです。

ちょっとメモリ番地を直接覗いてみましょうかしら

IBase::valueの場所

上記はa.Setterメソッド実行直後のダンプ値ですよ。
これを見ると確かに100が入ったね。

じゃ次。

IBase::valueの場所

b.Setterメソッドを通過するとちょっとわかりづらいですが、200が入ってます。

あらま。

なんという事。

というか、どういう事?🙄
そういう動きをする機能がstaticなのかと理解せざるを得ない結果ですが、実を言うとその理由がよく分かってないです。。。

とりあえず上記の動きをするみたいだから、クラス図のほうでクラス間で値を共有する手段としてインターフェースを設ける仕組みにしようとしました。

それが正攻法なのかどうかが分からないですが、なんか抽象クラス使っとけばそれでいいんじゃない?(ちょっと雑)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です