3

Abstract_things へのポインターのリストを持つ My_list クラスがあります。メモリの使用を最適化するために、すべての派生モノは、「新規および削除」ステレオタイプで確立された 1 つのメモリ プールを使用します。アプリケーションの初期化中にプールのサイズを適切に設定するために、ビルダーはどの Thing が最大であるかを判断し、それに基づいてプールのサイズを決定します。

設計上のジレンマは、新しいモノがモデルに追加された場合 (赤い Thing_4 で表される)、設計者はロジックを調整するために Builder に移動する必要があることです。私たちのチームがこれを行うことを覚えておくのは非常に困難であることに気付きました (約半分のモノが Builder で考慮されていませんでした)。将来の世代がこれを見落としてしまうことを非常に懸念しています。

私の質問は、どうすればこれを改善できますか? Thing_4 クラスを作成する過程で、max_size のすべてが自動的に処理されるとしたら素晴らしいことです。方法が思い浮かびませんが。

注: 写真を確認すると、間違いがあることに気付きました。コード ボックスの最後の行は、Abstract_thing::set_max_pool_size(max_size, max_number) となるはずです。

編集:画像を表示する方法がわかりません。プレビュー ウィンドウではすべて問題ないように見えますが、公開すると表示されません。何か助けはありますか?

編集:もう少し背景を説明すると、これは安全性が重要なシステムの組み込みアプリケーションの設計の一部です。アプリケーションの初期化中にヒープからメモリを割り当てることができますが、その初期化フェーズを終了した後は、動的メモリを割り当てることはできません。これを試みると、アプリケーションがクラッシュします。したがって、使用するインスタンスの最大サイズと最大数に合わせてプログラムします。すべての派生オブジェクトに十分なスペースを含む 1 つのプールを用意する方が、派生オブジェクトごとにプールを用意するよりも優れた方法です。

代替テキスト http://img262.imageshack.us/img262/4470/designproblemof1.png

4

5 に答える 5

3

更新:わかりました...組み込みシステムの要件により、状況が多少変わります。

クラスを使用して派生クラスを自動的に登録し、このクラスの静的インスタンスを各派生クラスに追加できます。あなたはまだこれをすることを覚えておく必要があります、しかし少なくともそれは単一の場所に自己完結しています。

何かのようなもの:

template<class T>
class RegisterPoolClass
{
public:
    RegisterPoolClass() { init_pool.Register(sizeof(T)); }
};

class Thing_1 : public Abstract_Thing
{
   static RegisterPoolClass<Thing_1> sInitializer;
    ...
};

RegisterPoolClass<Thing_1> Thing_1::sInitializer;

マクロを使用して、ATLと同じ方法で、各派生クラスに必要なコードをカプセル化できます。

于 2008-11-12T00:42:31.867 に答える
0

これを正しく理解しているかどうかはわかりませんが、派生クラスをすべて列挙し、現在使用している方法でサイズを推定して最大のものを見つけるビルドステップを実行できない理由は何ですか?

于 2008-11-12T00:38:52.700 に答える
0

クラスのgrepを使用して、すべてのサイズをテストし、混乱した場合に失敗するアプリを作成します。

echo '#include"head"' > out.cpp
grep "class \w+ : TheClass" *.cpp | sed  "s/.*class \(\w\)+ : TheClass.*/assert(sizeof($1) <= MAX_SIZE); >> out.cpp
echo '#include"tail"' >> out.cpp
gcc out.cpp
./a.out
于 2008-11-12T00:43:56.077 に答える
0

これはどう:

AbstractThing.h
#ifndef ABSTRACT_THING
#define ABSTRACT_THING
class AbstractThing
{
private:
    static  size_t                  maxChildSize;
    static  bool                    maxChildLock;
    static  std::vector<type_info>  validChildren;

    static size_t   getMaxChildSize()
    {
        maxChildLock    = true;
        return maxChildSize;
    }
public:
    template<typename T>
    static  void setChildSize()
    {
        // This is to stop registering things after getMaxChildSize()
        // has been called. This check is only needed during testing
        if (maxChildLocked)
        {
            exit(1);
        }
        maxChildSize    = std::max(maxChildSize,sizeof(T));
        validChildren.push_back(typeid T);
    }
    template<typename T>
    static bool testValidType()
    {
        // While testing call this method.
        // Don't call in production to speed things up.

        // Only registered children will be allowed to get memory.
        // Or maybe generate a warning in the log if it fails.
        return validChildren.find(typeid T) != validChildren.end();
    }
};
template<typename T>
class RegisterAbsoluteThing
{
public:
    RegisterAbsoluteThing()
    {
        AbstractThing::setChildSize<T>();
    }
};
#endif
Thing1.h
#ifndef THING_1
#define THING_1

#include "AbstractThing.h"
class Thing1: public AbstractThing
{
};

namespace
{
    // Because this is in an anonymous namespace
    // It does not matter how many times different files it is included
    // This will then all be registered at startup before main.
    RegisterAbsoluteThing<Thing1>   RegisterAsValidThing1;

    // All class that derive from AbstractThing should have this block.
    // Any that do not that try and use the pool will cause the tests to fail.
}
#endif
于 2008-11-12T00:44:52.377 に答える
0

CTAGS または同様のパーサーを使用してすべての派生クラスの名前を抽出し、それを使用して init_pool 実装を自動生成できますか?

于 2008-11-12T01:50:31.823 に答える