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

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

Страниц: 1 ... 10 11 [12] 13   Вниз
  Печать  
Автор Тема: Как писать ООП программы?  (Прочитано 86620 раз)
8Observer8
Гость
« Ответ #165 : Февраль 28, 2014, 20:25 »

Вот что-то радиус не меняет.  Грустный
Так он и не будет. У вас весь просчет окружности происходит в конструкторе. Вам нудно вынести его в отдельный метод и вызывать его после любого изменения радиуса.

А-а-а точно! Улыбающийся Большущее спасибо! Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #166 : Февраль 28, 2014, 20:26 »

Viewer'у необходимо перерисовывать пока программа работает. Вот ситуация, когда объекты удалились до их показа:
И что, удаленные объекты все равно рисуются Непонимающий
Ну хз, может в радиофизике "так надо" (др разумного объяснения не вижу)
Записан
8Observer8
Гость
« Ответ #167 : Февраль 28, 2014, 20:33 »

Нет конечно Улыбающийся

Это пример плохого кода. Их можно удалить и после показа, тогда viewer'у тоже нечего будет рисовать.
Записан
8Observer8
Гость
« Ответ #168 : Февраль 28, 2014, 20:51 »

А с shared_ptr указатели не нужно удалять, и viewer'у это наруку Улыбающийся

Код
C++ (Qt)
#include <QApplication>
#include "shape.h"
#include "rectangle.h"
#include "circle.h"
#include "triangle.h"
#include "viewer.h"
#include <utility>
#include <iostream>
#include <memory>
#include <QDebug>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   Viewer viewer;
   viewer.resize(400, 200);
 
   std::shared_ptr<myShapes::Shape> pr2(new myShapes::Rectangle(100.0, 25.0));
   std::shared_ptr<myShapes::Shape> pr3(new myShapes::Rectangle(100.0, 25.0));
   std::shared_ptr<myShapes::Shape> pt(new myShapes::Triangle(30.0, 50.0));
   std::shared_ptr<myShapes::Shape> pc(new myShapes::Circle(50.0));
 
   viewer.addForPainting(pt);
   viewer.addForPainting(pc);
   viewer.addForPainting(pr2);
   viewer.addForPainting(pr3);
 
   viewer.show();
 
   std::dynamic_pointer_cast<myShapes::Circle>(pc)->setRadius(25.0);
 
   return a.exec();
}
 
Записан
8Observer8
Гость
« Ответ #169 : Февраль 28, 2014, 21:04 »

А вот по поводу перерасчёта координат при изменении радиуса. Я должен очистить массив координат и заполнить поновой.

Может же возникнуть такая ситуация, что viewer узнает размер массива координат и начнёт считывать точки. А вот в это время пользователь изменит радиус. Массив координат очистится. И viewer обратится по неправильному индексу.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #170 : Февраль 28, 2014, 21:09 »

А с shared_ptr указатели не нужно удалять, и viewer'у это наруку Улыбающийся
Непонимающий Поясните идею. Вот допустим радиус Circle изменился - надо перерисовать сцену с учетом нового радиуса. Причем здесь удалять/не удалять? Ведь число рисуемых объектов никак не изменилось
Записан
8Observer8
Гость
« Ответ #171 : Февраль 28, 2014, 21:12 »

А с shared_ptr указатели не нужно удалять, и viewer'у это наруку Улыбающийся
Непонимающий Поясните идею. Вот допустим радиус Circle изменился - надо перерисовать сцену с учетом нового радиуса. Причем здесь удалять/не удалять? Ведь число рисуемых объектов никак не изменилось

Я не понял вопроса Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #172 : Февраль 28, 2014, 21:37 »

Ну правда, стоит лишь запомнить "С приведение = плохо. С++ приведение = хорошо" - и все (якобы) освоил Улыбающийся
Вам нужно переставать смотреть видеокурсы "С++ за 5 дней". Улыбающийся
Вроде вы уже наскакивали на виртуальное наследование.

В действительности "С приведение" с полным правом может считаться "expert mode" - все оно прекрасно сделает, вот только если неправильно - нет ошибки, ничего не скажет. Ну так ведь на то и "эксперт"  Улыбающийся
А здесь можно тешить себя как угодно. Можете даже считать его "God mode". Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #173 : Февраль 28, 2014, 21:39 »

Может же возникнуть такая ситуация, что viewer узнает размер массива координат и начнёт считывать точки. А вот в это время пользователь изменит радиус. Массив координат очистится. И viewer обратится по неправильному индексу.
Такая ситуация возможна только, если программа использует несколько потоков. Но тут и средства будут другие.
Записан
8Observer8
Гость
« Ответ #174 : Февраль 28, 2014, 21:53 »

Может же возникнуть такая ситуация, что viewer узнает размер массива координат и начнёт считывать точки. А вот в это время пользователь изменит радиус. Массив координат очистится. И viewer обратится по неправильному индексу.
Такая ситуация возможна только, если программа использует несколько потоков. Но тут и средства будут другие.

Да, точно! Получается, что когда мы внутри функции отрисовки, то ничего другого выполняться не будет. И так же, когда координаты генерируем и в это время нужно перерисовать, то код отрисовки "будет ждать" пока не выполнится генерация координат.
Записан
Johnik
Крякер
****
Offline Offline

Сообщений: 339


Просмотр профиля
« Ответ #175 : Март 01, 2014, 00:13 »

Значит, я полиморфизм неправильно понял. Видимо, перепутал с ситуацией, когда в производном переопределяется функция с ключевым словом "virtual".

Статический полиморфизм (с шаблонами) пока в сторону. Нужно лучше динамический проработать.

А как привести?

Код
C++ (Qt)
(myShapes::Shape)pc->setRadius(25.0);
 
Предлагаю пока оставить приведение типов в покое и проработать все без него, тем более оно тут пока и не нужно.
Вообще стоит понять, где нужен полиморфизм, а где нет.

Ваш код можно написать примерно так:
Код:
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
 
    Viewer viewer;
    viewer.resize(400, 200);
 
    myShapes::Rectangle pr2(100.0, 25.0);
    myShapes::Rectangle pr3(100.0, 25.0);
    myShapes::Triangle pt(30.0, 50.0);
    myShapes::Circle pc(50.0);
 
    viewer.addForPainting(&pt);      // объявление должно выглядеть так: void Viewer::addForPainting(myShapes::Shape* shape)
    viewer.addForPainting(&pc);
    viewer.addForPainting(&pr2);
    viewer.addForPainting(&pr3);
 
    viewer.show();
 
    // и тогда код без проблем можно будет написать:
    //std::dynamic_pointer_cast<myShapes::Circle>(pc)->setRadius(25.0);
    pc.setRadius(25.0);

    return a.exec();
}
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #176 : Март 01, 2014, 03:19 »

Ваш код можно написать примерно так:
Ну если цель только избавиться от приведения, то достаточно в коде ТС просто изменить тип указателя:

Код
C++ (Qt)
#include <QApplication>
#include "shape.h"
#include "rectangle.h"
#include "circle.h"
#include "triangle.h"
#include "viewer.h"
#include <utility>
#include <iostream>
#include <memory>
#include <QDebug>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   Viewer viewer;
   viewer.resize(400, 200);
 
   std::shared_ptr<myShapes::Shape> pr2(new myShapes::Rectangle(100.0, 25.0));
   std::shared_ptr<myShapes::Shape> pr3(new myShapes::Rectangle(100.0, 25.0));
   std::shared_ptr<myShapes::Shape> pt(new myShapes::Triangle(30.0, 50.0));
   std::shared_ptr<myShapes::Circle> pc(new myShapes::Circle(50.0));
 
   viewer.addForPainting(pt);
   viewer.addForPainting(pc);
   viewer.addForPainting(pr2);
   viewer.addForPainting(pr3);
 
   viewer.show();
 
   pc->setRadius(25.0);
 
   return a.exec();
}
 
Записан
8Observer8
Гость
« Ответ #177 : Март 01, 2014, 07:41 »

std::shared_ptr<myShapes::Circle> pc(new myShapes::Circle(50.0));
myShapes::Circle pc(50.0);

Эти два примера абсолютно эквивалентные. В первом - объект создаётся динамически (из кучи), во втором - статически (в стеке).

Теперь я понял, что объекты не обязаны иметь статический тип Shape для передачи в функцию, которая принимает указатель на объект базового класса.
« Последнее редактирование: Март 01, 2014, 08:12 от 8Observer8 » Записан
8Observer8
Гость
« Ответ #178 : Март 01, 2014, 07:54 »

Я понял, что в моём примере идеально подходят умные указатели (shared_ptr). Viewer, принимая указатели на внешние объекты, может быть спокоен, что объект действительно существует (кстати, должен ли он проверять непустой ли указатель?) Допустим, я решил не использовать умные указатели и единственный способ заставить viewer рисовать - это не удалять объекты выделенные из кучи. Если я точно знаю, что объектов будет не слишком много, то могу ли я себе позволить не удалять объекты выделенные динамически? Даже с умными указателями, объекты просуществуют столько же, как если не удалять с помощью delete. Вот так:

Код
C++ (Qt)
#include <QApplication>
#include "shape.h"
#include "rectangle.h"
#include "circle.h"
#include "triangle.h"
#include "viewer.h"
#include <utility>
#include <memory>
#include <QDebug>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   Viewer viewer;
   viewer.resize(400, 200);
 
   myShapes::Triangle *pt = new myShapes::Triangle(30.0, 50.0);
   myShapes::Circle *pc = new myShapes::Circle(50.0);
   myShapes::Rectangle *pr1 = new myShapes::Rectangle(100.0, 25.0);
   myShapes::Rectangle *pr2(new myShapes::Rectangle(100.0, 25.0));
 
//    std::shared_ptr<myShapes::Triangle> pt(new myShapes::Triangle(30.0, 50.0));
//    std::shared_ptr<myShapes::Circle> pc(new myShapes::Circle(50.0));
//    std::shared_ptr<myShapes::Rectangle> pr1(new myShapes::Rectangle(100.0, 25.0));
//    std::shared_ptr<myShapes::Rectangle> pr2(new myShapes::Rectangle(100.0, 25.0));
 
   viewer.addForPainting(pt);
   viewer.addForPainting(pc);
   viewer.addForPainting(pr1);
   viewer.addForPainting(pr2);
 
   viewer.show();
 
   pc->setRadius(25.0);
 
   return a.exec();
}
 
« Последнее редактирование: Март 01, 2014, 08:10 от 8Observer8 » Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #179 : Март 01, 2014, 09:21 »

Я понял, что в моём примере идеально подходят умные указатели (shared_ptr).
Как и для всего остального. Улыбающийся

(кстати, должен ли он проверять непустой ли указатель?)
Конечно. Пользователь класса Viewer может легко передать пустой указатель, поэтому лучше всего проверять указатель при добавлении объекта в методе addForPainting.

могу ли я себе позволить не удалять объекты выделенные динамически?
Сможете, главное не забыть удалить их потом.

Воспользуйтесь typedef'ами, с ними значительно понятней.
Код
C++ (Qt)
#include <QApplication>
#include "shape.h"
#include "rectangle.h"
#include "circle.h"
#include "triangle.h"
#include "viewer.h"
#include <utility>
#include <memory>
#include <QDebug>
 
namespace myShapes
{
 
typedef std::shared_ptr<Triangle> TrianglePtr;
typedef std::shared_ptr<Circle> CirclePtr;
typedef std::shared_ptr<Rectangle> RectanglePtr;
 
}
 
using namespace myShapes;
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   Viewer viewer;
   viewer.resize(400, 200);
 
   TrianglePtr pt(new myShapes::Triangle(30.0, 50.0));
   CirclePtr pc(new myShapes::Circle(50.0));
   RectanglePtr pr1(new myShapes::Rectangle(100.0, 25.0));
   RectanglePtr pr2(new myShapes::Rectangle(100.0, 25.0));
 
   viewer.addForPainting(pt);
   viewer.addForPainting(pc);
   viewer.addForPainting(pr1);
   viewer.addForPainting(pr2);
 
   viewer.show();
 
   pc->setRadius(25.0);
 
   return a.exec();
}
 
Записан
Страниц: 1 ... 10 11 [12] 13   Вверх
  Печать  
 
Перейти в:  


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