Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ Создание неограниченного количества элементов

Автор: RazrFalcon 2.7.2010, 19:31

К примеру по нажатии кнопки рядом появляется еще одна кнопка.
Как это реализовать, так как надо каждый раз давать имя новому элементу(кнопке).

pushButton_1->...
pushButton_2->...
pushButton_3->...
...
pushButton_n->...
PS желательно чтоб действие по нажатии главной кнопки передавалось и остальным (если нажму 50-ю кнопку тоже появится еще одна)
PSS ну или к примеру вставить QgraphicsView в каждую ячейку таблицы, пусть даже при условии что картинка на нем будет одна и та же.

Автор: Litkevich Yuriy 2.7.2010, 20:24

RazrFalcon, в этой ситуации я всем рекомендую смотреть пример "Calculator" (examples\widgets\calculator)

Автор: RazrFalcon 2.7.2010, 21:31

Цитата(Litkevich Yuriy @ 2.7.2010, 20:24) *
рекомендую смотреть пример "Calculator" (examples\widgets\calculator)

Что то не очень проясняется... разве что кроме
     for (int i = 0; i < NumDigitButtons; ++i) {
         digitButtons[i] = createButton(QString::number(i), SLOT(digitClicked()));
     }

Автор: Litkevich Yuriy 2.7.2010, 23:44

тепло, теперь разберись, как определяется, какую кнопку нажали.

Автор: Гость 9.7.2010, 3:30

Пришол из этой темы
Вот собственно код, что здесь не так?.
Жалуется, что конструктор у QPushButton private

main.cpp

CODE
#include "text_button.h"

int main(int argc, char **argv)
{
QApplication app(argc,argv);
QWidget wgt;
text_button *buttonNew = new text_button;

QPushButton *mainbtn = new QPushButton("Add Button");

QVBoxLayout *vbl = new QVBoxLayout();
vbl->addWidget(mainbtn);
wgt.setLayout(vbl);

/* Добавить класс для создания поля и кнопки */

QPushButton btn = buttonNew->NewButton();
//vbl->addWidget(btn);

wgt.show();
/*
QObject::connect(&mainbtn, SIGNAL(clicked()),
&buttonNew, SLOT(NewButton())
);
*/
return app.exec();
}


text_button.h
CODE
#ifndef TEXT_BUTTON_H
#define TEXT_BUTTON_H

#include <QObject>
#include <QtGui>
class text_button : public QObject
{
Q_OBJECT
public:
explicit text_button(QObject *parent = 0);
QPushButton NewButton();
signals:

public slots:
void clickMainBtn();

};

#endif // TEXT_BUTTON_H


text_button.cpp
CODE
#include "text_button.h"


text_button::text_button(QObject *parent) :
QObject(parent)
{
/*Все объекты должны создаваться в конструкторе */
}
QPushButton text_button::NewButton()
{
QPushButton *btn1 = new QPushButton("new");
//wgt->addWidget(btn1);
//cout << btn1 << endl;
return btn1;
}
void text_button::clickMainBtn()
{
//emit NewButton();
}


Я понимаю, что неплохо было бы передать виджет в класс как родитель, но дело не в правильности кода, а в понимании..

Автор: haiflive 9.7.2010, 4:11

Всё вопрос снят, разобрался..
Чуть позже выложу рабочий пример.. авось кому пригодится..
Будь они не ладны эти указатели..

Автор: Litkevich Yuriy 9.7.2010, 6:34

haiflive, в Qt у всех наследников QObject конструктор копирования и оператор присваивания находятся в закрытой (private) области. Т.к. операции копирования таких объектов не тривиальные. Поэтому всюду в программах Qt используется динамическое создание объектов-наследников QObject. Ну и соответственно работать с такими объектами нужно через указатель.

Автор: haiflive 9.7.2010, 15:14

Как-то в голове не укладывается, что вопрос решился обёрткой на базовый QT класс..

Тоесть, всё что нужно было, это создать новый класс отнаследованый от требуемого объекта(в данном случае QPushButton), и конструктор нового класса объявить как public?.
И всё работает.. :huh: или всётаки могут быть какие-то проблемы?.

#ifndef BUTTON_H
#define BUTTON_H

#include <QToolButton>

class Button : public QPushButton
{
     Q_OBJECT

public:
     Button(const QString &text, QWidget *parent = 0);

     QSize sizeHint() const;
};

#endif

Автор: Алексей1153 10.7.2010, 6:19

ИМХО, лучше так

#pragma once
#include <QToolButton>

class Button
{
     QPushButton* m_pButton;

public:
     Button(/*...параметры...*/)
     {
         m_pButton=new QPushButton(/*...параметры...*/);
     }

     ~Button()
     {
         if(m_pButton)delete m_pButton;
     }

     operator QPushButton()
     {
         return *m_pButton;
     }

     Button(const QString &text, QWidget *parent = 0);

     QSize sizeHint() const;

    QPushButton& GetQPushButton()
    {
        return *m_pButton;
    }
};



а ещё лучше - массив указателей и не париться по ерунде )

Автор: Litkevich Yuriy 10.7.2010, 11:03

Как-то всё очень сложно, пример "Калькулятор" явно не был изучен

Автор: haiflive 13.7.2010, 6:05

А деструктор зачем?. Разве MOC не берёт на себя удаление объектов?. может всётаки лучше Q_OBJECT

И интересно посмотреть, как с этим классом работать..

Автор: Litkevich Yuriy 13.7.2010, 12:01

Цитата(haiflive @ 13.7.2010, 10:05) *
Разве MOC не берёт на себя удаление объектов?
MOC ни когда не занимался удалением объектов

Автор: haiflive 13.7.2010, 14:48

Цитата(Litkevich Yuriy @ 13.7.2010, 20:01) *
MOC ни когда не занимался удалением объектов


Ничего не понимаю, если классы наследуются от QObject и объекты создаются с помошью оператора new, то деструкторы описывать надо?.

Автор: Litkevich Yuriy 13.7.2010, 16:33

Цитата(haiflive @ 13.7.2010, 18:48) *
то деструкторы описывать надо?.
если у них нет родителя, то надо самому удалять (смотри описание аргумента parent, в конструкторе класса QObject)

Автор: Алексей1153 13.7.2010, 18:43

Цитата(haiflive @ 13.7.2010, 9:05) *
А деструктор зачем?. Разве MOC не берёт на себя удаление объектов?. может всётаки лучше Q_OBJECT

Видимо, тут ещё надо учесть то, что было передано в конструкторе - если был родитель, то вызывать delete, если не было, то не вызывать. Но тогда существует опасность работы с несуществующей уже кнопкой (класс-обёртку надо ещё как-то известить, что кнопка удалилась извне)

Цитата(haiflive @ 13.7.2010, 9:05) *
И интересно посмотреть, как с этим классом работать..

Как работать - если нужен доступ к членам экземпляра QPushButton, то вызывается GetQPushButton()
Button BUT;
BUT.GetQPushButton().member;


В случаях, когда QPushButton должен быть передан как параметр, указатель и так далее (в том числе при работе с операторами), можно использоваться прямо экземпляр класса Button (см. оператор Button::operator QPushButton() )

(подправил, кстати, - убрал лишний амперсенд в типе оператора)

Автор: MoPDoBoPoT 14.7.2010, 10:07

Цитата(Алексей1153 @ 13.7.2010, 19:43) *
Видимо, тут ещё надо учесть то, что было передано в конструкторе - если был родитель, то вызывать delete, если не было, то не вызывать. Но тогда существует опасность работы с несуществующей уже кнопкой (класс-обёртку надо ещё как-то известить, что кнопка удалилась извне)

Для этого есть void QObject::destroyed ( QObject * obj = 0 ) [signal]

Автор: Алексей1153 14.7.2010, 14:06

Ну вот, значит в классе дописать слот и связать в конструкторе с данным сигналом QPushButton. А в слоте просто обнулить указатель-мембер

Автор: RazrFalcon 15.7.2010, 15:18

Ого как тема разрасталась пока я забросил эту затею, ну вот все таки доделал то что требовалось. Выложил упрощенный вариант проги своей.
Был использован пример Calculator и переписана функция создания кнопок, может кому пригодится.

PS: правда так и не смог избавится от формы, выдавалась "Ошибка вида: QWidget: Must construct a QApplication before a QPaintDevice" (название темы на форуме встречал такое же). Буду благодарен за способ ухода от форм. Так как особо навороченным интерфейсом не интересуюсь.

PSS: ну а если надо совсем просто то можно и так:

    //создаем 10 бесполезных кнопок
    for (int i=0; i<10; i++)
    {
        QPushButton* button = new QPushButton();
        tableWidget->setCellWidget(i,0,button);
    }
Правда кнопки не несут никакого действия, зато пригодилось мне для создания "неограниченного количества" QgraphicsView, очень удобно.
PSS: обновил файл, переделал немного

 button.zip ( 3.55 килобайт ) : 98
 

Автор: haiflive 19.7.2010, 15:41

Ну вот наконец-то я осилил пример с кнопкой..
Создаётся кнопка при нажатии на которую создаётся аналогичная(++N), и так до бесконечности..
и представляю код на ваш суд..

button.h

#ifndef BUTTON_H
#define BUTTON_H

#include <QToolButton>

class Button : public QToolButton
{
     Q_OBJECT

public:
     Button(const QString &text, QWidget *parent = 0);

     QSize sizeHint() const;
};

#endif

button.cpp
#include <QtGui>

#include "button.h"

Button::Button(const QString &text, QWidget *parent)
     : QToolButton(parent)
{
     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
     setText(text);
}

QSize Button::sizeHint() const
{
     QSize size = QToolButton::sizeHint();
     size.rheight() += 20;
     size.rwidth() = qMax(size.width(), size.height());
     return size;
}

text_button.h
#ifndef TEXT_BUTTON_H
#define TEXT_BUTTON_H

#include <iostream>
#include <QObject>
#include <QtGui>
/*
* можно не использовать класс "button.h" и писать вместо
* Button *button = new Button("new"+QString::number(Schet));
* QToolButton *button = new QToolButton("new"+QString::number(Schet));
* но так удобнее
*/
#include "button.h"
class text_button : public QObject
{
    Q_OBJECT
    /* Здесь будут храниться все указатели на кнопки */
    QMap<int,Button*> mapNewButtons;
    int Schet; /* счётчик кнопок */
public:
    explicit text_button(QObject *parent = 0);
    Button *NewButton();
    void MAddButton();
signals:

public slots:
    void clickMainBtn();

};

#endif // TEXT_BUTTON_H

text_button.cpp
#include "text_button.h"

text_button::text_button(QObject *parent) :
    QObject(parent), Schet(0)
{

}
Button *text_button::NewButton()
{
    Button *button = new Button("new"+QString::number(Schet));
/* Можно обработать кнопку сразу при создании */
/*
    QObject::connect(button, SIGNAL(clicked()),
                     this, SLOT(clickMainBtn())
                     );
*/
    qDebug() << SLOT(clickMainBtn());
    return button;
}
void text_button::MAddButton()
{
    /* Конечно можно было всё это сделать внутри функции NewButton(),
    * но цель была показать как работать между классами
    * имеено поэтому понадобился контейнерс с указателями */
    mapNewButtons[++Schet] = NewButton();
    mapNewButtons[Schet]->show();
    /* Прикручиваем сигнал "создать новую кнопку"
    * к только что созданной кнопке */
    QObject::connect(mapNewButtons[Schet], SIGNAL(clicked()),
                     this, SLOT(clickMainBtn())
                     );
}

void text_button::clickMainBtn()
{
    emit MAddButton();
}

main.cpp
#include "text_button.h"

int main(int argc, char **argv)
{
    QApplication app(argc,argv);
    QWidget wgt;
    /* Первая кнопка */
    QPushButton mainbtn("Add new Button");
    QVBoxLayout vbl;

    text_button buttonNew; /* Класс дл создания N кнопок */

    vbl.addWidget(&mainbtn);
    wgt.setLayout(&vbl);
    /* Здесь мы просто создаём новую кнопку используя наш класс */
    Button *btn = buttonNew.NewButton();
    /* аналогично можно работать с новой кнопкой */
    vbl.addWidget(btn);

    wgt.show();
    /* Создаём для певой главной кнопки сигнал
    * "создать новую кнопку" используя наш класс */
    QObject::connect(&mainbtn, SIGNAL(clicked()),
                     &buttonNew, SLOT(clickMainBtn())
                     );

     return app.exec();
}

Автор: Litkevich Yuriy 20.7.2010, 15:46

тему разделил: http://www.forum.crossplatform.ru/index.php?showtopic=5288

Автор: RazrFalcon 12.8.2010, 20:07

Опять не известно количество элементов.
1) Человек вводит число и создается такое же количество qgraphicsview, как потом к ним обращаться.
2) -//- checkbox
С кнопками и примером калькулятора уже не получится так как там используется QToolButton
Идей пока не каких.

Автор: Litkevich Yuriy 12.8.2010, 20:26

Цитата(RazrFalcon @ 13.8.2010, 0:07) *
1) Человек вводит число и создается такое же количество qgraphicsview, как потом к ним обращаться.
задай вопрос "снаружи", а не "изнутри". Т.е. как человек будет с ними взаимодействовать? Что он хочет получить, создав множество элементов?

Автор: RazrFalcon 12.8.2010, 20:51

Litkevich Yuriy, что то типа множества слоев, ака gif анимация покадрово.
Нужно для начала сделать чтоб был аналог flowlayout, только пример мне как то не очень понравился, другим способом хочу.
а для checkbox, грузится список из файла, и человек выбирает нужные пункты. Заранее не известно понятное дело сколько их.
Как создать и обратится к элементу, любому, если я не знаю будет он создан или нет. :huh:
Типа qgraphicsview_1, qgraphicsview_2, qgraphicsview_3 ... а потом к нужному обращаться, но не знаю сначала скока х будет то!

Автор: Litkevich Yuriy 12.8.2010, 21:02

RazrFalcon, ты опять про внутренности.
Как человек работает с твоей программой? что он делает?

Автор: RazrFalcon 12.8.2010, 21:15

Бээ... пользователь ввел число 10. Появилось 10 qgraphicsview. Потом он нажал на один правой кнопкой мыши и выбрал добавить изобраение, и оно должно загрузится именно в этот qgraphicsview. Потом нажал закрыть/удалить и он удалился. Потом поменять и 4-й стал 6-м. Потом растянул окно и они и 2х5 штук стали 3х3 и еще 1-н в низу короче. То есть аналог flowlayout из кьюшных примеров. Потом говорит сохранить некоторые к примеру. Появляется список с checkbox и он ставит галочки напротив нужных кадров и сохраняет.
Вот, чисто со стороны пользователя.
PS qgraphicsview двигаю через ResizeEvent+setGeometry
PSS такое чуство что я не вижу что то явное и обыкновенное.

Автор: BRE 12.8.2010, 21:19

Цитата(RazrFalcon @ 12.8.2010, 22:15) *
PSS такое чуство что я не вижу что то явное и обыкновенное.

Может семейство классов-коллекций?
Посмотри на QList, QMap, ...

Автор: Litkevich Yuriy 12.8.2010, 21:49

Цитата(RazrFalcon @ 13.8.2010, 1:15) *
Потом он нажал на один правой кнопкой мыши и выбрал добавить изобраение, и оно должно загрузится именно в этот qgraphicsview
в программе ты всегда можешь узнать по какому графическому элементу щёлкнул пользователь или выделил его (спрашивай у сцены).
Каждый элемент должен обладать определёнными возможностями, например, хранить ссылку (путь или что-то ещё) на картинку.
Цитата(RazrFalcon @ 13.8.2010, 1:15) *
Потом поменять и 4-й стал 6-м.
вот это не понял, в смысле передвинуть с одного места на другое? ну пусть двигает, каркас графического представления уже содержит необходимую функциональность. Если необходимо связывать номера с элементами, пусть у элемента будет соответствующая пара методов (установить номер, прочитать номер). Перенумерацию можно делать силами сцены (сделав наследника от стандартной).
Цитата(RazrFalcon @ 13.8.2010, 1:15) *
Потом растянул окно и они и 2х5 штук стали 3х3 и еще 1-н в низу короче. То есть аналог flowlayout из кьюшных примеров.
этот кусок кода и взять из примеров

Автор: RazrFalcon 12.8.2010, 22:10

BRE, спасибо, то что нужно, как оказалось.

QList<QWidget *> list;
list.append(graphicsView);
list[0]->setGeometry(0,0,50,50);
Ну и производные отсюдова вещи.
Но это работает только если я разместил на форме graphicsView, а если сделать так:
QGraphicsView* graphicsViev = new QGraphicsView();
то ничего не выходит, пустое окно. <_<
И тогда второй вопрос, как такой способ создания занести в цикл, не так же:
QGraphicsView* graphicsViev[i] = new QGraphicsView();

Автор: Алексей1153 12.8.2010, 22:14

Цитата(RazrFalcon @ 13.8.2010, 1:10) *
QGraphicsView* graphicsViev = new QGraphicsView();
то ничего не выходит, пустое окно.

а виджет невидимым создаётся вроде бы :) Его показать нужно

Цитата(RazrFalcon @ 13.8.2010, 1:10) *
И тогда второй вопрос, как такой способ создания занести в цикл

QList<QGraphicsView *> list;
for(int i=0;i<N;i++)
{
   list.append(new QGraphicsView(this));
}



А ещё не забывать про висячие указатели, когда виджеты покоцаны ))

Автор: Litkevich Yuriy 12.8.2010, 22:19

Цитата(RazrFalcon @ 13.8.2010, 2:10) *
а если сделать так:
а ты точно потом этим виджетом пользуешся?

RazrFalcon, а тебе вообще за каким лешим такое кол-во графических представлений?

Автор: RazrFalcon 12.8.2010, 22:28

Алексей1153, что значит показать, у меня обычно они так видны (все что я таким способом создавал), а при setVisible/show просто отдельный виджет появляется с graphicsViev. Циклом твои тоже ничего не видно, хотя компилит. Спасибо за цикл кстати.
Litkevich Yuriy, ну их создается ровно столько сколько нужно, циклом, так что лишних нет.
я же писал, что то типа раскадровки гиф/видео, там же их будет 1000-чи...

Автор: Алексей1153 12.8.2010, 22:43

RazrFalcon, ну, предположим, он видим. Но ты указатель на родительский виджет не передаёшь

Цитата
new QGraphicsView();

может, тут сябака порылась? )


Цитата(RazrFalcon @ 13.8.2010, 1:28) *
что то типа раскадровки гиф/видео, там же их будет 1000-чи...


достаточно столько вьюх, сколько влезет на экран. Остальное - организовать "логическое окно" просмотра (вроде как цепь протягивают в трубе, а в трубе есть 5 отверстий - видно одновременно 5 кадров-звеньев)

Автор: RazrFalcon 12.8.2010, 23:14

Алексей1153, спасибо за идею попробую ограничится только влезшими на экран.
Спасибо всем, все работает.
Создаем:

    QList<QGraphicsView *> list;
    for(int i=0;i<10;i++)
    {
       list.append(new QGraphicsView(this));
    }
Изменяем:
int x=0, y=0;
   for (int i=0; i<list.count();i++)
   {
      list[i]->setGeometry(x,y,50,50);
      x+=51;
      y+=51;
    }

PS (this) помог, я как то раньше не обращал внимания.
PSS еще б с http://www.forum.crossplatform.ru/index.php?showtopic=5270 разобраться =)

Автор: Алексей1153 13.8.2010, 6:45

RazrFalcon, ещё два момента:

1) поскольку QList<QGraphicsView *> list предположительно - член класса, то перед циклом заполнения не забывай проверить, сколько элементов уже есть в списке. Не забывай также удалить через delete (как вариант, можно сделать оболочку для указателя, чтобы не приходилось вызывать delete вручную - щас приведу ниже)

Раскрывающийся текст
//вумный указатель для хранения в векторе и иже с ним
    template<typename T>
    struct s_VectorPtr
    {
        T* m_p;

        s_VectorPtr()
        {
            m_p=0;
        }

        s_VectorPtr(const s_VectorPtr& o2)
        {
            m_p=0;
            (*this)=o2;
        }

        void createIfNotYet()
        {
            if(!m_p)
            {
                m_p=new T;
            }
        }

        ~s_VectorPtr()
        {
            if(m_p)
            {
                delete m_p;
                m_p=0;
            }
        }

        void operator=(const s_VectorPtr& o2)
        {
            if(m_p)
            {
                delete m_p;
                m_p=0;
            }

            T* p=o2.m_p;
            ((s_VectorPtr&)o2).m_p=0;
            m_p=p;
        }

        T* operator ->()
        {
            return m_p;
        }
    };


//обявление теперь выглядит так
QList< s_VectorPtr<QGraphicsView> > list;//тут "*" не надо!


теперь, если изменение размера вектора влечёт за собой удаление элементов, delete вызовется автоматом


2)число 10 - это от балды. Тут следует сделать динамическую прикидку количества вьюх

Автор: BRE 13.8.2010, 7:59

Алексей1153, для чего столько всего в деструкторе? ;)

    ~s_VectorPtr()
    {
        if(m_p)
        {
            delete m_p;
            m_p=0;
        }
    }


достаточно просто:
    ~s_VectorPtr()
    {
        delete m_p;
    }


По стандарту delete умеет работать с 0-указателями, он их проверяет и ничего не удаляет.
Зануление указателя в деструкторе тоже бессмыслено, сразу после этого объект все равно разрушиться.

Автор: Алексей1153 13.8.2010, 8:05

BRE, проверка if(m_p) здесь обязательна: смотри работу operator= :) Стандарт стандартом, но грабли потом искать не хочется, если что

ну а обнуление висячего указателя - это просто полезная привычка

Автор: BRE 13.8.2010, 8:07

Цитата(Алексей1153 @ 13.8.2010, 9:05) *
BRE, проверка if(m_p) здесь обязательна: смотри работу operator= :)

В деструкторе, перед delete?
А для чего? :)

Цитата(Алексей1153 @ 13.8.2010, 9:05) *
ну а обнуление висячего указателя - это просто полезная привычка

Самая полезная привычка в программировании это постоянно думать что делаешь, а не полагаться на автоматизм.

Автор: Алексей1153 13.8.2010, 8:11

Цитата(BRE @ 13.8.2010, 11:07) *
перед delete

именно перед ним :) Про грабли я уже сказал, а ещё, бывает, люди переопределяют delete. Автоматизмом тут не пахнет

Ну а думать - это всегда пожалуйста, работа такая )) Но некоторые вещи отработаны до автоматизЬма - это экономит время и сокращает глюки (и колическтво разъярённых клиентов)

Поэтому, если так сильно хочется, можно и удалить "лишний код", но это бессмысленно - на быстродействии это не скажется всё равно

Автор: BRE 13.8.2010, 8:16

Цитата(Алексей1153 @ 13.8.2010, 9:11) *
именно перед ним :) Про грабли я уже сказал, а ещё, бывает, люди переопределяют delete. Автоматизмом тут не пахнет

Именно перед ним эта проверка абсолютно бессмысленна.
Какие грабли?
А если люди переопределяют delete, то делают эту проверку первой. Как-то странно забыть ее сделать в delete и не забывать ее делать во всех остальных местах. :)

Автор: Алексей1153 13.8.2010, 8:20

Хорошо, пусть будет так:

    ~s_VectorPtr()
    {
#ifdef BRE
        delete m_p;
#else
        if(m_p)
        {
            delete m_p;
            m_p=0;
        }
#endif
    }


;)

Автор: BRE 13.8.2010, 8:27

Алексей1153, я вовсе не занудствую. :)
Ты предлагаешь свой код человеку, который учиться. Этот код избыточен. Для чего учить человека писать избыточный код?
У тебя это вошло в привычку, но не обязательно (и, наверное, не правильно), что бы это вошло в его привычку. Отсюда и мой комментарий. ;)

Автор: Алексей1153 13.8.2010, 8:34

BRE, дык, я ж ничего. У всех свой стиль, он прочитает всё, что мы тут понаписали - и выберет теперь свой стиль. Правильно рассуждаю ? ))

Автор: DEADHUNT 13.8.2010, 10:25

Цитата(Алексей1153 @ 13.8.2010, 7:45) *
Не забывай также удалить через delete (как вариант, можно сделать оболочку для указателя, чтобы не приходилось вызывать delete вручную

зачем делать то, что уже сделали в C++0x/boost/Qt? причём данная реализация не совсем корректна (нету конструктора копирования, нету конструктора перемещения(для C++0x), и прочие мелочи)

Автор: Алексей1153 13.8.2010, 10:39

DEADHUNT, я вообще про C++ речь веду. А где, кстати, в Qt это есть?

А про "не совсем корректность" - так вектору не нужен конструктор копирования и прочие мелочи, там оператор присваивания только нужен. Всё остальное -

"избыточность кода" © BRE
:)

Ненужные препирательства всё это. Я подсказал путь, а решений - туча, каждому нравится своё

Автор: DEADHUNT 13.8.2010, 14:00

Цитата(Алексей1153 @ 13.8.2010, 11:39) *
А где, кстати, в Qt это есть?

QScopedPointer/QSharedPointer

Цитата(Алексей1153 @ 13.8.2010, 11:39) *
А про "не совсем корректность" - так вектору не нужен конструктор копирования и прочие мелочи, там оператор присваивания только нужен.

посмотри стандарт, там есть требования к элементам контейнера - конструктор по умолчанию, конструктор копирования, деструктор, etc.
в твоем примере получается что ты не реализовал конструктор копирования, компилятор создал его(но не так как требует семантика умного указателя).

Автор: Litkevich Yuriy 13.8.2010, 15:53

Цитата(Алексей1153 @ 13.8.2010, 12:05) *
смотри работу operator=
оператор - член класса, т.к. мы в деструкторе, то объект собрался умирать вместе с его операторами. BRE прав, тут ты переборщил с осторожностью.

хотя у меня такое тоже встречается, но тому причиной простой копипаст.

Автор: Алексей1153 13.8.2010, 16:08

а где сей стандарт глядеть?

А насчёт корректности работы - оно работает, одного только оператора присваивания достаточно. Правда, у меня в проекте std::vector используется, но работает без ошибок - очень хорошо и длительно тестировано :)

Автор: DEADHUNT 13.8.2010, 16:47

http://open-std.org/JTC1/SC22/WG21/docs/papers/2010/n3090.pdf

насчёт работы это как раз из-за твоего зануления указателя в деструкторе, потому-что деструктор вызывается несколько раз вместо одного, попробуй сделать так в своём классе:

class smart_ptr {
    smart_ptr(const smart_ptr &);
....
};

или так
class smart_ptr {
    smart_ptr(const smart_ptr &) = delete;
....
};

и увидешь где используется конструктор копирования.

Автор: Litkevich Yuriy 13.8.2010, 17:33

DEADHUNT, не мог бы ты пояснить такую строчку:

Цитата(DEADHUNT @ 13.8.2010, 20:47) *
smart_ptr(const smart_ptr &) = delete;
?

Автор: Алексей1153 13.8.2010, 17:54

Синтаксис я тоже не понял :) что означает "= delete" и "= default" после прототипа функции?

Автор: DEADHUNT 13.8.2010, 19:27

Цитата(DEADHUNT @ 13.8.2010, 17:47) *
Синтаксис я тоже не понял :) что означает "= delete" и "= default" после прототипа функции?

= delete/default применяется только к специальным членам класса(конструктор, конструктор копирования, ...), delete обозначает то что компилятор не должен генерировать default версию этого специального члена класса, а при попытке вызова выдавать ошибку компиляции(это равносильно объявиления данного члена закрытым и не реализовывать). default показывает компилятору что он должен создать default версию данного члена, например:
class some_class {
public:
   some_class() = default;
   some_class(int a) : m_a(a) { }
private:
   int m_a;
};

some_class a;
some_class a(10);

иначе бы компилятор не стал создавать конструктор по умолчанию.

Автор: Алексей1153 13.8.2010, 20:26

понятно

то есть мне нужно добавить

        s_VectorPtr(const s_VectorPtr& o2)
        {
            m_p=0;
            (*this)=o2;
        }

Автор: DEADHUNT 13.8.2010, 20:38

Цитата(Алексей1153 @ 13.8.2010, 21:26) *
то есть мне нужно добавить

это же разрушающее копирование получается(если ещё посмотреть код operator=), т.е. что-то типа std::auto_ptr, а их нельзя в контейнерах использовать, надо что-то типа shared_ptr делать, то есть хранить количество ссылок на указатель, ...

Автор: Алексей1153 13.8.2010, 20:49

DEADHUNT, так так, тут вот поподробнее. Почему разрушающее? Я копирую указатель в новую оболочку, а сам "указуемый" объект жив.

Это вот в операторе = у меня заменяемый объект отправляется в кучу, а принимаемый его заменяет

Почему нельзя в контейнере использовать, ведь контейнер ничего неиспортит, вызывая конструкторы и операторы

Я главную цель всей этой эпопеи не сказал (думал, и так понятно) - безопасное использование resize() контейнера + автоудаление "указуемых" объектов в кучу

Автор: DEADHUNT 13.8.2010, 20:57

получается так:

X<T> b = ...;
X<T> a(b); // b - передаёт указатель a

std::vector<X<T>> v;
v.push_back(a); // a - разрушается
v.front(); // разрушается объект в векторе


и ещё непонятно зачем operator= принимает константную ссылку, а внутре изменяет содержимое константного объекта, лучше было бы в параметре использовать не константную ссылку.

Автор: Алексей1153 13.8.2010, 21:07

Я не собирался отдельно объявлять переменные класса s_VectorPtr<T> , всем этим заведует сам вектор (структура s_VectorPtr, кстати, в проекте, откуда выдрано, описана как приватная внутри класса с вектором)

Теперь я понимаю твоё возмущение, а также , почему у меня всё работает, хотя, по стандарту, не должно :) Я реализовал и использовал частный случай

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)