Russian Qt Forum
Октябрь 01, 2024, 12:34 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как создать копию объекта, зная его указатель?  (Прочитано 9341 раз)
alexeev
Гость
« : Октябрь 22, 2013, 10:36 »

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

Ты же при создании объекта QwtPolarPlot какими-то параметрами его выставляешь в нужное состояние? Вот создай новый и теми же параметрами приведи его к нужному виду
Записан
alexeev
Гость
« Ответ #2 : Октябрь 22, 2013, 10:41 »

Это плохое решение, таких графиков много, для постраения каждого используется много данных, разные структуры.
Записан
mutineer
Гость
« Ответ #3 : Октябрь 22, 2013, 10:42 »

А нужна ли копия вообще? Открывающееся окно модальное? Если да, то может можно тот же самый объект отобразить?
Записан
alexeev
Гость
« Ответ #4 : Октябрь 22, 2013, 10:44 »

Не знаю, что такое модальное) Простое создаю новый виджет, на него хочу положить новый объект. Если добавлю просто указатель, то график пропадет на главном окне. Новое окно служит для увеличения графика. Это типа того, если вы в поисковике картинки ищите, видете маленький варинат, но нажав на картинку открывается большой.
Записан
schmidt
Гость
« Ответ #5 : Октябрь 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
« Последнее редактирование: Октябрь 29, 2013, 01:00 от Schmidt » Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #6 : Октябрь 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....
}
« Последнее редактирование: Октябрь 30, 2013, 00:10 от _Bers » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Октябрь 30, 2013, 11:28 »

Код:
void Foo(base* ptr)
{
     //как мне получить копию объекта?
     base* copy = ?
}
}
Определить
Код
C++ (Qt)
virtual base * clone( void ) const;
 
Ну или пригнуться и перебрать все dynamic_cast  Улыбающийся
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #8 : Октябрь 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)
-- аллоцировать в куче
-- аллоцировать на стеке
-- аллоцировать в пуле памяти


К чему я про это начал: вопрос, который был озвучен в теме - это вопрос наличия приличного инструментария под рукой.
Стандартных средств нет. Но сделать можно.
« Последнее редактирование: Октябрь 30, 2013, 22:35 от _Bers » Записан
schmidt
Гость
« Ответ #9 : Октябрь 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() могла получить доступ куда угодно!". Очевидно, что С++ не рассчитан на такое варварство Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Октябрь 31, 2013, 10:48 »

3. Перебор динамик_кастом - это вообще из области говнокода. Полиморфизм не для этого придумали.
Безусловно, это говнокод. Но когда человек вот так "рубит с плеча" - то, вероятно, ужиться с ним в проекте будет трудно  Улыбающийся

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


Страница сгенерирована за 0.199 секунд. Запросов: 22.