C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: C++の内部クラスの静的メンバの初期化


(過去ログ 52 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■28718 / inTopicNo.1)  C++の内部クラスの静的メンバの初期化
  
□投稿者/ hijiki (1回)-(2008/11/29(Sat) 13:13:24)

分類:[C/C++] 

こんにちは。
C++の文法で質問があります。

何でも良いのですが、例えば木構造のクラスを作るとします。
そのクラスの中で節を表すNODEクラスを作り、そのNODEクラスに、木の末端を現すNONEというconst NODE*型のstaticなメンバを作ろうとしてみます。

template<
class DATA = int
>class Tree{
class NODE{
public:
DATA data;
NODE *right,*left;
static const NODE* NONE;
//省略
NODE( DATA d ){
data = d;
left = ( NODE* )( NODE::NONE );//こんな風に使いたいです
right = ( NODE* )( NODE::NONE );
}
};
NODE *root;
Tree(){
root = ( NODE* )NODE::NONE; //こんな風に使いたいです
}
};

こういう場合、NONEの初期化はどのように行ったらよいでしょうか?

私は頭が良くありませんし、経験も豊富ではないです。
どうか助けてください。
よろしくお願いします。
引用返信 編集キー/
■28719 / inTopicNo.2)  Re[1]: C++の内部クラスの静的メンバの初期化
□投稿者/ 774RR (242回)-(2008/11/29(Sat) 13:31:44)
そういう static の使い方をすると、その Tree だか Node だかよくわからないけど
1つしか作れなくなっちゃうのでダメ
設計の見直しを推奨する
引用返信 編集キー/
■28722 / inTopicNo.3)  Re[1]: C++の内部クラスの静的メンバの初期化
□投稿者/ dogatana (15回)-(2008/11/29(Sat) 16:10:30)
No28718 (hijiki さん) に返信

> C++の文法で質問があります。

static const メンバの初期化ということであれば、次のようにできます。
(参考:EffectiveC++ 改訂第2版 1項)
クラスの宣言の中で初期値を入れる方がより新しい形式とのことです。
この例に限定した話であれば、NONEなんて使わずに0で良いのではと思いますが。。

#include <iostream>

class HogeClass {
public:
    void show() {
        std::cout <<
            "hoge1 = " << hoge1 << std::endl <<
            "hoge2 = " << hoge2 << std::endl;
    }
private:
    static const int hoge1 = 123;
    static const int hoge2;
};

const int HogeClass::hoge2 = 456;

int main()
{
    HogeClass aHoge;
    aHoge.show();  // うまくいくかな?
}

引用返信 編集キー/
■28726 / inTopicNo.4)  Re[2]: C++の内部クラスの静的メンバの初期化
□投稿者/ hijiki (2回)-(2008/11/29(Sat) 18:39:39)
お返事ありがとうございます。

なんでTREEだかNODEが一度だけしか作れなくなってしまうのでしょうか?
インスタンスによらず共通のNONEにアクセスするようになるだけではないですか?
勉強不足ですみません。

また、この問題が起きたのは赤黒木を作っているときなのでNULLとNONEを明示的に分けたほうが便利です。また、NODEに0はムリです。

ちなみにクラス内で初期化できる静的メンバは整数型だけですのでdogatanaさんのメンバは初期化で着ますがそれ以外、例えば上のNODE型は初期化できません。

普通静的なメンバクラスはクラス外で初期化しますので、

const Tree<>::NODE::NODE *( Tree<>::NODE::NODE::NONE ) = new Tree<>::NODE(0);

という感じでクラス外で初期化すればTree<int>型でNONEが使えるようになるかと思ったのですが、templateデ指定するKEY型を外から堂指定するのか分からなかったのですが、取り合えずNONEにKEY型の値を与える必要はないので、諦めてNODE(){}という何もしないコンストラクタを追加して

const Tree<>::NODE::NODE *( Tree<>::NODE::NODE::NONE ) = new Tree<>::NODE::NODE();

というようにするようにしました。

引用返信 編集キー/
■28727 / inTopicNo.5)  Re[3]: C++の内部クラスの静的メンバの初期化
□投稿者/ hijiki (3回)-(2008/11/29(Sat) 18:39:48)
No28726 (hijiki さん) に返信
> お返事ありがとうございます。
>
> なんでTREEだかNODEが一度だけしか作れなくなってしまうのでしょうか?
> インスタンスによらず共通のNONEにアクセスするようになるだけではないですか?
> 勉強不足ですみません。
>
> また、この問題が起きたのは赤黒木を作っているときなのでNULLとNONEを明示的に分けたほうが便利です。また、NODEに0はムリです。
>
> ちなみにクラス内で初期化できる静的メンバは整数型だけですのでdogatanaさんのメンバは初期化で着ますがそれ以外、例えば上のNODE型は初期化できません。
>
> 普通静的なメンバクラスはクラス外で初期化しますので、
>
> const Tree<>::NODE::NODE *( Tree<>::NODE::NODE::NONE ) = new Tree<>::NODE(0);
>
> という感じでクラス外で初期化すればTree<int>型でNONEが使えるようになるかと思ったのですが、templateデ指定するKEY型を外から堂指定するのか分からなかったのですが、取り合えずNONEにKEY型の値を与える必要はないので、諦めてNODE(){}という何もしないコンストラクタを追加して
>
> const Tree<>::NODE::NODE *( Tree<>::NODE::NODE::NONE ) = new Tree<>::NODE::NODE();
>
> というようにするようにしました。
>
引用返信 編集キー/
■28771 / inTopicNo.6)  Re[3]: C++の内部クラスの静的メンバの初期化
□投稿者/ dogatana (17回)-(2008/11/30(Sun) 19:27:18)
dogatana@実はC++勉強中

ちょっと自信がなくなってきましたが、足りない知恵を絞って見ました ^^;

■No28726 (hijiki さん) に返信
> また、この問題が起きたのは赤黒木を作っているときなのでNULLとNONEを明示的に分けたほうが便利です。また、NODEに0はムリです。

NODEの役割が不明だったのですが、left/rightの初期値として使用されているので、末端ではないかと推測。
で、木構造で一般に末端を表すのにNULLポインタを使用するのでその代替じゃないかと推測したのですが。
NULLポインタ以外に、特定のオブジェクトを指すポインタが必要で、このオブジェクトの左右の部分木への
ポインタが自分自身を指すということでしょうか。

それはともかく、強引にやろうと思うと次のようなコードでできそうです。
コンパイルエラーは出ませんが、left/rightへは0が代入されてしまいます。
Nodeのコード生成時にはNONEが0で初期化されてしまうためだと推測しますが、自信なしです ^^;

#個人的には特殊なオブジェクトが必要な場合はそれを使う側、この場合だとTreeで準備するのが
#自然に思います・・


#include <iostream>

template<typename T>
class Tree {
public:
    Tree() {
        root = const_cast<Node * const>(Node::NONE);
    }
    void test() {
        std::cout << "root = " << reinterpret_cast<unsigned int>(root) << std::endl;
        std::cout << "root->left = " << reinterpret_cast<unsigned int>(root->left) << std::endl;
        std::cout << "root->right = " << reinterpret_cast<unsigned int>(root->right) << std::endl;
        std::cout << "NONE = " << reinterpret_cast<unsigned int>(Node::NONE) << std::endl;
        root->show();
        Node::NONE->show();
    }
private:
    class Node {
    public:
        void show() const {
            std::cout << "data = " << data << " " 
                << ((left == NONE)? "none": "exist") << " "
                << ((right == NONE)? "none": "exist") << std::endl;
        }
        Node(int n = 0): data(n) {
            left  = const_cast<Node * const>(NONE);
            right = const_cast<Node * const>(NONE);
        }
        T   data;
        Node *left, *right;
        static const Node *NONE;
    };
    Node* root;
};

template<typename T>
const typename Tree<T>::Node* Tree<T>::Node::NONE = 
   new typename Tree<T>::Node;

int main()
{
    Tree<double> a;
    a.test();
    Tree<double> b;
    b.test();
}



引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -