-1

Qtライブラリを使用してアプリケーションのコントロールパネルを作成したいので、このためにクラス Controlsクラスを作成します

Controls:スライダーを作成し、スピンとラベルを作成して、水平レイアウトで配置します。

しかし、エラーなしで実行されるプログラムを作成したいのにstd::vector<Controls>、コントロールがまったく作成されていない場合!では、なぜコントロールがないのですか。

Controls.h

class Controls 
{

private:

    QHBoxLayout Layout ;
    string Controlname;
    std::auto_ptr<QLabel> Label ;
    std::auto_ptr<QSlider> Slider ;
    std::auto_ptr<QSpinBox> Spin ;

public:
    Controls();
    Controls(QLayout &Parent , string name , const int &Default_value);
    Controls(const Controls &copy);
    ~Controls();

    QLabel *const Get_Label()const { return Label.get() ; }
    QSlider *const Get_Slider()const { return Slider.get() ; }
    QSpinBox *const Get_Spin()const { return Spin.get() ; }
    QHBoxLayout *const Get_Layout() {return &Layout;}

    void SetValue(const int &newvalue);

    Controls &operator= (const Controls &copy);


};

Controls.cpp

Controls &Controls::operator= (const Controls &copy)
{

Label = std::auto_ptr<QLabel> ( new QLabel() ) ;
Slider = std::auto_ptr<QSlider> ( new QSlider() ) ;
Spin = std::auto_ptr<QSpinBox> ( new QSpinBox() ) ;

    this->Controlname = copy.Controlname ;
    this->Slider.get()->setValue( copy.Slider.get()->value() );
    this->Spin.get()->setValue( copy.Spin.get()->value() );

    return *this ;
}
Controls::Controls(const Controls &copy)
{
    this->Controlname = copy.Controlname ;
    this->Slider.get()->setValue( copy.Slider.get()->value() );
    this->Spin.get()->setValue( copy.Spin.get()->value() );

}
Controls::Controls()
{

    Label = std::auto_ptr<QLabel> ( new QLabel() ) ;
    Slider = std::auto_ptr<QSlider> ( new QSlider() ) ;
    Spin = std::auto_ptr<QSpinBox> ( new QSpinBox() ) ;

    Slider->setValue(0);
    Slider->setOrientation(Qt::Horizontal);
    Label->setText(QString ("unamed"));
    Spin->setValue(0);


    Layout.addWidget(Label.get() , 0 , 0);
    Layout.addWidget(Slider.get() , 0 , 0);
    Layout.addWidget(Spin.get() , 0 , 0);

    QObject::connect(Slider.get() , SIGNAL(valueChanged(int) ) , Spin.get() , SLOT(setValue(int)));
    QObject::connect(Spin.get() , SIGNAL(valueChanged(int) ) , Slider.get() , SLOT(setValue(int)));

}
Controls::Controls(QLayout &Parent , string name , const int &Default_value)
{
    Controlname = name ;

    Label = std::auto_ptr<QLabel> ( new QLabel() ) ;
    Slider = std::auto_ptr<QSlider> ( new QSlider() ) ;
    Spin = std::auto_ptr<QSpinBox> ( new QSpinBox() ) ;

    Slider->setValue(Default_value*100);
    Slider->setOrientation(Qt::Horizontal);
    Label->setText(QString (name.c_str()));
    Spin->setValue(Default_value*100);


    Layout.addWidget(Label.get() , 0 , 0);
    Layout.addWidget(Slider.get() , 0 , 0);
    Layout.addWidget(Spin.get() , 0 , 0);

    QObject::connect(Slider.get() , SIGNAL(valueChanged(int) ) , Spin.get() , SLOT(setValue(int)));
    QObject::connect(Spin.get() , SIGNAL(valueChanged(int) ) , Slider.get() , SLOT(setValue(int)));

    Parent.addItem(&Layout);

}

void Controls::SetValue(const int &newvalue)
{
    Slider.get()->setValue(newvalue);
}
Controls::~Controls()
{

}

main.cpp

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


    QApplication app (argc , argv );


    QVBoxLayout layout ;
    auto_ptr<QWidget> Panel = auto_ptr<QWidget> (new QWidget()) ;

    vector<Controls> g ;
    g.push_back(Controls(layout , "WHITE_BALANCE_RED_V" , 56 ));

        Panel.get()->setLayout(&layout);
    Panel.get()->show();

        return app.exec();

}

編集:

auto_ptrデストラクタを〜controlsから削除し、再度実行すると、この例外が発生します

pure virtual method called
terminate called without an active exception
  • スライダーを初期化し、コピーコンストラクターでスピンします
4

2 に答える 2

3

ここには2つの「werid」なものがあり、すべてauto_ptrに関連しています。

1つは、メンバーのデストラクタが、埋め込みデストラクタの出口を過ぎたところで自動的に呼び出されることです。したがって、meber変数を明示的に破棄すると、コンパイラが管理するように設計されていない「二重破棄」が発生します。

(注:変数が「ポインター」と呼ばれるという事実は、それをもはや変数にすることはありません。生のポインターを使用し、呼び出すと、ポインターdelete pointerは破壊されませんが、ポインターは、 auto_ptrが単独で行うものです。 )。

2つ目は、auto_ptrコピーできないことです。実際には、コピー演算子を使用して移動セマンティクスを実装しますが、コンテナー(std :: vectorなど)は、コピーが...コピー(移動ではない)であると想定します。

ほとんどのstd::vector(およびstd :: listも)実装では、これは問題ではありません。これは、実装者がその点に注意を払い、コンテナーが同時に存在するコピーを生成することを回避するためです。しかし、一部のミューテーションアルゴリズムは、誤って間違った場所に「移動」したために、一貫して機能しません。関数が戻った直後に破棄されます...ため息をつきます!)

この2番目の側面は、C ++ 11によって解決されます。これは、コピー可能要素と移動可能要素の両方をサポートするコンテナーを実装し(R値参照を備えたC ++ 11であるため、コピーと移動は明確に区別される操作です)、実装を廃止auto_ptrします。 「コピーの上」ではなく「コピーの代わりにunique_ptr」「移動」します。

話の教訓:C ++ 11unique_ptrでは、の代わりに使用しauto_ptrます。

C ++ 03ではauto_ptr、コンテナ内またはコンテナ内に留まらなければならないオブジェクトでは使用しないでください。

生のポインターを使用して、適切な(オブジェクトの)コピーセマンティクスを定義する(「ディープコピー」を実行して、オブジェクトのコピーを指すポインターのコピーを作成する)または共有セマンティクス(同じオブジェクトを指すポインターを作成し、参照を管理する)尖った要素の破壊をトリガーするためにカウントします。boost::shared_ptrはそのような「ポインター」の例です)

于 2012-10-17T08:36:26.300 に答える
1

プログラムはエラーなしで実行されますが、コントロールはまったく作成されています!

メンバーがまだ初期化されていないため、0を返すControls::Controls(const Controls &copy)呼び出しを行っているため、これは実際には非常に奇妙です。this->Slider.get()

まず、使用方法を読んで理解する必要がありますauto_ptr

第二に、あなたはそれを忘れてauto_ptr、それ以上使用しないでください。Qtには独自のスマートポインターがありますが、QObjectは子の存続期間を管理するため、この場合は必要ありません。

したがって、第3に、Qtのメモリ管理について読み、それらのスマートポインタをすべて取り除きます。

于 2012-10-17T08:35:48.377 に答える