Russian Qt Forum

Программирование => С/C++ => Тема начата: alexeev от Октябрь 22, 2013, 10:36



Название: Как создать копию объекта, зная его указатель?
Отправлено: alexeev от Октябрь 22, 2013, 10:36
Здравствуйте, существует следующая проблема. В своей программе я рисую график используя класс QwtPolarPlot. По нажатию на график, должно открыться новое окно, в котором будет точно такой же график. Хорошим решением было бы либо передать в метод создания окна копию объекта QwtPolarPlot, но в этом классе не определен конструктор копии, поэтому так сделать нельзя. Можно ли как-то решить данную проблему?
Есть ещё один варинат, создать на новом окне объект QwtPolarPlot, получить список всех элементов находящихся на первом графике, и прикрепить к новому объекту, но список элементов получается как список указателей на эти объекты, поэтому прикрепляя их на новый объект, на старом они пропадают. Какждый элемент списка представляет из себя Qlist <QwtPolarItem*>, его объект тоже создать нельзя, т.к   QwtPolarItem - абстрактный класс. Как решить эту проблему?)


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: mutineer от Октябрь 22, 2013, 10:39
Ты же при создании объекта QwtPolarPlot какими-то параметрами его выставляешь в нужное состояние? Вот создай новый и теми же параметрами приведи его к нужному виду


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: alexeev от Октябрь 22, 2013, 10:41
Это плохое решение, таких графиков много, для постраения каждого используется много данных, разные структуры.


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: mutineer от Октябрь 22, 2013, 10:42
А нужна ли копия вообще? Открывающееся окно модальное? Если да, то может можно тот же самый объект отобразить?


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: alexeev от Октябрь 22, 2013, 10:44
Не знаю, что такое модальное) Простое создаю новый виджет, на него хочу положить новый объект. Если добавлю просто указатель, то график пропадет на главном окне. Новое окно служит для увеличения графика. Это типа того, если вы в поисковике картинки ищите, видете маленький варинат, но нажав на картинку открывается большой.


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: schmidt от Октябрь 29, 2013, 00:54
То, о чем вы говорите, зовется viewport или "область просмотра" :) Если у вас есть карта и вы хотите просто взглянуть на нее поближе, будет неестественно создавать для этого ее копию. Это называется "увеличением масштаба" ) Советую обратиться к документации по Model/View Framework в Qt (в оригинале: http://qt-project.org/doc/qt-5.0/qtwidgets/model-view-programming.html на русском: http://doc.crossplatform.ru/qt/4.7.x/model-view-programming.html ): там доступно расписано, как сделать так, чтоб ваши данные (карта/график/финансовая статистика) существуя в единственном экземпляре могли одновременно выводиться в различных представлениях (Views). Таким образом, написав класс (назовем его Viewport) в соответствии с идеологией классов-представлений ( http://doc.crossplatform.ru/qt/4.7.x/model-view-programming.html#view-classes ) вы получите независимое окно для дополнительной навигации по графику.


P.S. А копии объектов по их указателям создаются обычно с помощью конструкторов копирования, определенных в этих же классах :)
http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D0%BE%D1%80_%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: _Bers от Октябрь 29, 2013, 23:59
P.S. А копии объектов по их указателям создаются обычно с помощью конструкторов копирования, определенных в этих же классах :)
http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D0%BE%D1%80_%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F

Код:
struct base
{
    virtual ~base(){}
    virtual void Foo()=0;
};

struct der1: base
{
    virtual ~der(){}
    virtual void Foo(){}
};

struct der2: base
{
    virtual ~der2(){}
    virtual void Foo(){}
};

void Foo(base* ptr)
{
     //как мне получить копию объекта?
     base* copy = ?
}

int main()
{
      if( random(0,1)==0)
          base* ptr = new Der1;
      else
          base* ptr = new Der2;

     Foo(ptr);  // <--- Ups....
}


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: Igors от Октябрь 30, 2013, 11:28
Код:
void Foo(base* ptr)
{
     //как мне получить копию объекта?
     base* copy = ?
}
}
Определить
Код
C++ (Qt)
virtual base * clone( void ) const;
 
Ну или пригнуться и перебрать все dynamic_cast  :)


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: _Bers от Октябрь 30, 2013, 22:33
Определить
Код
C++ (Qt)
virtual base * clone( void ) const;
 
Ну или пригнуться и перебрать все dynamic_cast  :)

1. Определить можно не всегда (не всегда доступна возможность правки кода).
2. Clone в том виде, в каком его реализуют в 99,999% всех случаев, что я наблюдал - это использование динамической аллокации:
Код:
virtual base * clone( void ) const { return new Der};

Что неимоверно просаживает рантайм.
То есть, классическая работа с интерфейсами на плюсах в том виде, что она есть сейчас - не эффективна.
К сожалению нет стандартных средств для работы с интерфейсами.

3. Перебор динамик_кастом - это вообще из области говнокода. Полиморфизм не для этого придумали.


Я использую механизм собственного производства:

Код:
struct base
{
    virtual ~base(){}
    virtual void Foo()=0;
};

struct der1: base
{
    virtual ~der(){}
    virtual void Foo(){}
};

struct der2: base
{
    virtual ~der2(){}
    virtual void Foo(){}
};

void Foo( smart<base>& obj)
{
     //как мне получить копию объекта?

     //может создать независимую копию независимо от того, определен ли в объекте-ресурсе метод Clone
     smart<base> copy = obj.Clone();
}

int main()
{
      smart<base> obj;
      if( random(0,1)==0)
           obj.make<Der1>();
      else
           obj.make<Der2>();

     Foo(obj);  
}

Тот, кто конктролирует точку создания ресурса сможет сделать с ним все что угодно. И реализовывать какой угодно менеджмент:
-- шарить ресурс (ближайший аналог std::shared_ptr)
-- инжектить подсчет ссылок прямо в объект-ресурс (ближайший аналог boost::intrusive_ptr)
-- аллоцировать в куче
-- аллоцировать на стеке
-- аллоцировать в пуле памяти


К чему я про это начал: вопрос, который был озвучен в теме - это вопрос наличия приличного инструментария под рукой.
Стандартных средств нет. Но сделать можно.


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: schmidt от Октябрь 31, 2013, 05:34
Цитировать
1. Определить можно не всегда (не всегда доступна возможность правки кода).
2. Clone в том виде, в каком его реализуют в 99,999% всех случаев, что я наблюдал - это использование динамической аллокации:
Код:

virtual base * clone( void ) const { return new Der};


Что неимоверно просаживает рантайм.
То есть, классическая работа с интерфейсами на плюсах в том виде, что она есть сейчас - не эффективна.
К сожалению нет стандартных средств для работы с интерфейсами.

3. Перебор динамик_кастом - это вообще из области говнокода. Полиморфизм не для этого придумали.


Я использую механизм собственного производства:

Возникает резонный вопрос: если решение этой проблемы порождает столько проблем, что приходится писать собственные костыли в обход всех стандартов, не говорит ли это о том, что проблема совсем в другом месте? В архитектуре программы, в кривой реализации, в неправильно поставленной проблеме?:) 99.9% проблем, которые приводили к напилке шатких костылей удавалось решить, сформулировав проблемы иначе. Ну подумайте сами, не странным ли выглядит наличие в программе отдельно стоящей C-style функции Foo(), работающей с целой иерархией C++ классов? Назовите мне хоть одну причину, по которой невозможно сделать эту функцию виртуальной в классе Base?:) Если человек затрудняется точно объяснить почему ему обязательно требуется писать код вопреки всем стандартам и логике языка, это как бы намекает на то, что у него не код а манная каша.

Итого:
1. dynamic_cast - извращенный путь страданий, который жрет тем больше времени у программы, чем больше классов в иерархии.
2. Функция, которая работает с объектами некоторого класса - хороший кандидат на то, чтобы стать методом этого класса. Если работа этой функции зависит от конкретного типа класса-наследника, эта функция обязана быть виртуальной.
3. Если функция Foo() зависит и от других классов, скорее всего у автора в программе просто винегрет. Классы и объекты введены в язык для того, чтобы скрывать детали реализации определенной части программы от других ее частей. Выходит автор с одной стороны использует классы, пишеь конструкторы, методы, выстраивает иерархию, а с другой стороны говорит: "А теперь плевать я хотел на инкапсуляцию, хочу чтобы моя глобальная функция Foo() могла получить доступ куда угодно!". Очевидно, что С++ не рассчитан на такое варварство :)


Название: Re: Как создать копию объекта, зная его указатель?
Отправлено: Igors от Октябрь 31, 2013, 10:48
3. Перебор динамик_кастом - это вообще из области говнокода. Полиморфизм не для этого придумали.
Безусловно, это говнокод. Но когда человек вот так "рубит с плеча" - то, вероятно, ужиться с ним в проекте будет трудно  :)

Я использую механизм собственного производства:
А можно компилируемый пример? (интересно повникать, пока я не понял что к чему). Спасибо