0

i have a Controls class that have default constructor and copy constructor and other constructor ,and an assignment operator , and i want to create array of my class using vector . When i resize my vector i get the objects initialized correctly ; but when i want to create my objects using non default constructor i get this error ,

pure virtual method called terminate called without an active exception

Controls.h

class Controls : public QObject
{

private:

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

public:

    Controls(QLayout &Parent , string name , const int &Default_value);
    Controls(const Controls &copy);
    Controls();
    ~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() ) ;

    Slider->setValue(copy.Get_Slider()->value());
    Slider->setOrientation(Qt::Horizontal);
    Label->setText(QString ("unamed"));
    Spin->setValue(copy.Get_Spin()->value());


    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)));


    return *this ;
}
Controls::Controls(const Controls &copy)
{
    *this = copy ;
}
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);
    Slider->setOrientation(Qt::Horizontal);
    Label->setText(QString (name.c_str()));
    Spin->setValue(Default_value);


    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 ...... .

   vector <Controls> i ;
      i.resize(2 ); // this is work 

     i.push_back(Controls(layout , "WHITE_BALANCE_RED_V" ,12);// this is not working 
  • I guess it's just editing problem, but this line is bad already, it should be "i.push_back(Controls(layout , "WHITE_BALANCE_RED_V" ,12));" – progician Oct 18 '12 at 10:58
  • sorry! i forget point comma (i edit it now) , but i use it in my real code! and i get output : pure virtual method called terminate called without an active exception when i use push_back – user1728234 Oct 18 '12 at 11:03

4 Answers4

0

Also, I think the problem is with your auto_ptr variables. You should check if it is really the way how you want to treat your object pointers. I would rather stick with the shared_ptr or unique_ptr. In the latter case however, you don't want to have copy constructor at all, as there could be only one owner of the pointers.

C++ std::auto_ptr copy constructor

Community
  • 1
  • 1
progician
  • 910
  • 8
  • 15
0

I'm not sure that you are implementing your copy semantics correctly, and the use of std::auto_ptr as a data member is kind of an "alert sign".

Are your Controls really deep-copyable?

Maybe you should just use scoped_ptr instead of auto_ptr data members, ban copy declaring private copy constructor and private operator=, and use vector<shared_ptr<Controls>> ?

(Or use C++11 and move semantics, and so use unique_ptr instead of auto_ptr, and just use compiler automatically generated move operations?)

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
0

This has nothing to do with std::vector and non-default constructors. You did not provide the whole code, but I assume this is the continuation of the previous question.

Your Controls::operator= is invalid, it creates copies of QWidgets, and puts them into brand new QLayout. Controls object that you pass to push_back is temporary object that is destroyed after the call and it's copy is put into vector. But destroyed object's QWidget members are put into QLayout, which is not destroyed and which is added to the widget you try to show (Panel). After temporary Controls object is destroyed, Panel->show() calls Panel's QLayout methods that try to access already deleted widgets.

Do you really need to save copies of your Controls objects in your vector? If you store pointers, that would get rid of your problem. Why do you need that vector at all?

And once again, do not use auto_ptr, it's deprecated and you don't need it to correctly manage deletion of QObjects.

Community
  • 1
  • 1
Paul
  • 13,042
  • 3
  • 41
  • 59
  • Your Controls::operator= is invalid ; can you explain witch part is invalid and hank you – user1728234 Oct 18 '12 at 12:12
  • I already described - in `operator=` you create a new layout for destination `Controls` object and put copies of your widgets there. When source `Controls` object (that you copy from) is destroyed, widgets are also deleted (thanks to `auto_ptr`), but pointers to them are stored in `QVBoxLayout layout` object that you created on stack before. `layout` is then set up into `Panel`. When you call `Panel->show()` it calls methods of `QLayout` for `layout` object, which, in turn, tries to call methods of deleted widgets. – Paul Oct 18 '12 at 12:16
  • Please describe, why do you need to store copies of `Controls` objects in this vector? Can you store pointers? Do you need to store them at all? – Paul Oct 18 '12 at 12:42
  • i don't want to store copies of Controls , i want to store new Controls object . – user1728234 Oct 18 '12 at 12:44
  • Consider storing pointers then (but not auto_ptrs, you may store raw pointers or shared_ptrs or QSharedPtrs, whatever you like). `std::vector::resize` works just because it either don't copy anything (there's enough memory to just expand the vector storage) or because it copies default constructed `Controls` objects which are not used anywhere. – Paul Oct 18 '12 at 14:35
0

When using auto_ptr you should use release not get to pass the pointer to new owner:

Not this in Controls::Controls(QLayout &Parent , string name , const int &Default_value):

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

But that:

Layout.addWidget(Label.release() , 0 , 0);

Otherwise - your auto_ptr are deleting the pointers at the end of scope of this constructor.

PiotrNycz
  • 23,099
  • 7
  • 66
  • 112