0

私のclass実装では、次のようなものがあります。

基本クラス

class swcWidget :
     public swcRectangle
{
public:
    swcWidget();
    virtual ~swcWidget();

    void update(float dt);

protected:

    inline virtual void oPaintOnTop() { }
private:
};

派生クラス

class swcButton :
     public swcWidget
    ,public swcText
{
public:
    swcButton();
    virtual ~swcButton();

    static const int DEFAULT_SIZE = 20;

protected:
private:

    void oPaintOnTop();
};

class swcApplication
{
public:

    swcApplication(int argc, char *argv[]);
    virtual ~swcApplication();

    int run();

    struct Controls
    {
        typedef std::vector<swcWidget*> vWidgets;                 //option 1

        ~Controls();


          /////////////////////////////////
         //   M A I N   P R O B L E M   //
        /////////////////////////////////

        void add(swcWidget &&widgets);  //most preferred option
                                        //but gets demoted to base class.

        void add(swcWidget *widgets);   //second choice
                                        //but should I make a copy of it?
                                        //or just make a reference to it?
                                        //and this one does what I wanted to.
                                        //but still unsure on other things I don't know

        void add(swcWidget *&&widgets); //this compiles fine (?)
                                        //I don't know what kind of disaster I can make into this, but still does not do what I wanted.

        inline vWidgets &getWidgets() {
            return widgets;
        }

    private:

        vWidgets widgets;
    };

    Controls controls;

};

私はこのようないくつかの作業オプションを知っています:

を作る

swcApplication::Controls::widgets

のタイプとして

std::vector<std::shared_ptr<swcWidget>>

しかし、私のコードはバインドされstd::shared_ptr、次のような単純な構文を作成できません:

swcButton btn;
app.controls.add(std::move(btn));

使用例:

main.cpp

int main(int argc, char *argv[])
{

    swcApplication app(argc, argv);

    app.windows.create(640, 480);

    if (font->load("fonts\\georgia.fnt") != BMfont_Status::BMF_NO_ERROR)
    {
        puts("failed to load \"georgia.fnt\"");
    }

    {
        swcButton btn;

        btn.setPosition(100, 100);
        btn.setFont(font);
        btn.text = "Ey!";

        app.controls.add(std::move(&btn));

//      btn.text = "Oy!";

    }


    return app.run();
}

アップデート:

これは一時的な定義ですswcApplication::Controls::add()が、まだ異なる場合があります

void swcApplication::Controls::add(swcWidget &&widget)
{
    widgets.push_back(std::move(widget));
}
4

1 に答える 1

1

クラスが移動可能な場合は、そのメンバーを 1 つずつ移動します。これを効率的に行うには、これらのメンバーを小さな POD にするか、ヒープに割り当てる必要があります。メンバーを移動することを忘れずに、この機能を追加する必要があります。また、オブジェクトのスライスに注意する必要があります。

クラスが自明ではない場合、ポインターを直接使用するだけで最も効率的な移動構造を利用できます (もちろん、ヒープ割り当て時間は犠牲になります)。オブジェクト全体を一度に移動するため、スライスは不可能であり、メンバーの移動を忘れることはありません。注意すべきハードルの 1 つは、ポインターの所有者を追跡することです。それを確実に設定することをお勧めしますが、それが完了すれば、もう問題はありません。

移動のセマンティクスは素晴らしいですが、クラスが多少関係している場合は、この場合のポインターの方が作業が簡単/効率的だと思います。したがって、私はポインターバリアントに固執し、コレクションがポインターを所有することを確認します(そして、RAIIを介してそれらを再度解放します)-そう言うパブリックインターフェイスでコメントを自由に使用してください。これを行うには、何らかの形式のスマート ポインターを格納するか (ヒント: unique_ptr には注意してください!)、または (安全性が低い) コレクションを clear() する前にすべてのポインターを削除する Clear() メンバーを作成して常に使用します。

編集

ウィジェット メンバーを vector 型に定義すると、コード例は次のようになります。

クラス swcApplication に以下を追加します。

  void swcApplication::Controls::ClearWidgets() {
    for (auto& nextWidget: widgets) {
      delete nextWidget;
    }
    widgets.clear();
  }

適切なタイミングで (デストラクタなどで) ClearWidgets を呼び出すことを忘れないでください。

ウィジェットの追加は、次の方法で実行できます。

// Note: any passed widget will not be owned by you anymore!
template <typename Widget>
void swcApplication::Controls::add(Widget*& widget) {
  widgets.push_back(widget);
  widget = nullptr;
}

これからは、次のようなウィジェットを追加できます

swcButton* btn = new swcButton;
app.controls.add(btn);
// btn is now owned by app.controls, and should be set
// to nullptr for you to prevent misuse like deleting it

ここでスマート ポインターを使用すると、より安全になりますが、unique_ptr を格納すると、それらにアクセスするときにエラーが発生しやすくなります (コンテナーにアクセスするときに所有権をコンテナーから取り戻すことに注意してください)。

于 2014-02-11T08:26:38.910 に答える