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

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

Страниц: 1 ... 7 8 [9] 10 11 ... 13   Вниз
  Печать  
Автор Тема: Как писать ООП программы?  (Прочитано 86826 раз)
8Observer8
Гость
« Ответ #120 : Февраль 26, 2014, 13:49 »

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

Сообщений: 11445


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

Спасибо! В данном случае - понятно. А если это класс Person, в котором: имя, фамилия, отчество и возраст? Это довольно маленький класс.
Хороший показатель: есть ли оператор + (фактически он говорит что класс будет обыгрываться по значению). Др показатель - использует ли класс хоть какие-то распределения памяти - напр строки используют. Ну и редко но все же бывает что подача по значению выгодна задаче. Пример
Код
C++ (Qt)
typedef double Matrix[16];
void InvertMatrix( Matrix & dst, Matrix src );
В чем замысел программиста подавшего второй аргумент по значению?
« Последнее редактирование: Февраль 26, 2014, 13:56 от Igors » Записан
Hrundel
Гость
« Ответ #122 : Февраль 26, 2014, 20:07 »

У меня в итоге только один вопрос: научился ли ТС  писать ООП программы? Смеющийся
Записан
BuRn
Гость
« Ответ #123 : Февраль 26, 2014, 20:23 »

У меня в итоге только один вопрос: научился ли ТС  писать ООП программы? Смеющийся
ИМХО тема из серии "Как скачать интернет"
Записан
8Observer8
Гость
« Ответ #124 : Февраль 26, 2014, 20:41 »

Пример
Код
C++ (Qt)
typedef double Matrix[16];
void InvertMatrix( Matrix & dst, Matrix src );
В чем замысел программиста подавшего второй аргумент по значению?

Замысел в том, чтобы не испортить матрицу-источник.

Мне кажется, здесь ошибка (здесь нет матрицы) и нужно было так написать:

Код
C++ (Qt)
#include <QCoreApplication>
 
const std::size_t NR = 5;
const std::size_t NC = 10;
 
typedef int m1[NC];
typedef m1 Matrix[NR];
 
void InvertMatrix(Matrix &dst, Matrix src) {
 
}
 
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
 
   Matrix matrix;
 
   return a.exec();
}
 
Записан
8Observer8
Гость
« Ответ #125 : Февраль 27, 2014, 07:45 »

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

Вот моя идея, на примере класса Rectangle:

- В базовом абстрактном классе Shape, я реализовал хранение пар координат в динамическом массиве. Координаты точек рассчитываются во время создания объекта и сохраняются в массив. Точку можно получить по индексу:

Код
C++ (Qt)
#ifndef SHAPE_H
#define SHAPE_H
 
#include <vector>
#include <utility>
 
namespace myShapes {
 
class Shape
{
public:
   // ...
 
   std::pair<int, int> point(int index) const {
       return m_points[index];
   }
 
protected:
   void addPoint(int x, int y) {
       m_points.push_back(std::make_pair(x, y));
   }
 
private:
   std::vector<std::pair<int, int> > m_points;
   //...
};
 
}
 
#endif // SHAPE_H
 

В функции main() я создаю объект класса Viewer и "скармливаю" ему объекты с динамическим типом Rectangle. Я хочу чтобы объект класса Viewer хранил копии объектов Rectangle и др. для перерисовывания. Хранить копии объектов нужно для функции paintGL(), которая вызывается, когда объект нужно перерисовать.

Но я пришёл к такой ситуации, что мне оказывается нужно хранить объекты класса Shape, а этого нельзя сделать, потому что нельзя создать объекты абстрактного класса.

Код
C++ (Qt)
#ifndef VIEWER_H
#define VIEWER_H
 
#include <QGLWidget>
#include "shape.h"
 
#include <vector>
 
class Viewer : public QGLWidget
{
public:
   Viewer(QWidget *pwgt = 0);
 
   void addForPainting(const myShapes::Shape &ps) {
       m_shapes.push_back(ps);
   }
 
protected:
   virtual void initializeGL();
   virtual void resizeGL(int nWidth, int nHeight);
   virtual void paintGL();
 
private:
   std::vector<myShapes::Shape> m_shapes;
};
 
#endif // VIEWER_H
 
« Последнее редактирование: Февраль 27, 2014, 07:48 от 8Observer8 » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #126 : Февраль 27, 2014, 08:04 »

Зато можно хранить указатель или ссылку на абстрактный класс.
Записан
8Observer8
Гость
« Ответ #127 : Февраль 27, 2014, 08:08 »

Да, но у меня в main объекты быстро удаляются:

Код
C++ (Qt)
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   Viewer viewer;
   viewer.resize(400, 200);
 
   myShapes::Shape *pr1 = new myShapes::Rectangle(5.0, 10.0);
   myShapes::Shape *pr2 = new myShapes::Rectangle(5.0, 10.0);
   myShapes::Shape *pr3 = new myShapes::Rectangle(5.0, 10.0);
   myShapes::Shape *pr4 = new myShapes::Rectangle(5.0, 10.0);
   myShapes::Shape *pr5 = new myShapes::Rectangle(5.0, 10.0);
 
   viewer.addForPainting(*pr1);
   viewer.addForPainting(*pr2);
   viewer.addForPainting(*pr3);
   viewer.addForPainting(*pr4);
   viewer.addForPainting(*pr5);
 
   delete pr1;
   delete pr2;
   delete pr3;
   delete pr4;
   delete pr5;
 
   viewer.show();
   return a.exec();
}
 
« Последнее редактирование: Февраль 27, 2014, 10:43 от 8Observer8 » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #128 : Февраль 27, 2014, 08:24 »

Работайте с умными указателями, тогда объекты указателей в функции создания фигур быстро удаляться, а сами объекты фигур остануться жить, пока указатели на них будут храниться в списке viewer.
« Последнее редактирование: Февраль 27, 2014, 08:28 от Old » Записан
8Observer8
Гость
« Ответ #129 : Февраль 27, 2014, 08:33 »

Работайте с умными указателями, тогда объекты указателей в функции создания фигур быстро удаляться, а сами объекты фигур остануться жить, пока указатели на них будут храниться в списке viewer.

Огромное спасибо! Я теперь смогу изучить работу с умными указателями на практике Улыбающийся

P.S. Позже напишу о результатах.
Записан
8Observer8
Гость
« Ответ #130 : Февраль 27, 2014, 11:50 »

Посмотрите, пожалуйста, мой маленький демонстрационный пример. Корректно ли я работаю с умными указателями:

Output:
Цитировать
Name of the Shape: Rectangle
Name of the Shape: Circle

Код
C++ (Qt)
#include <QCoreApplication>
#include <memory>
#include <vector>
#include <string>
#include <iostream>
 
//----------------- class Shape -----------------
class Shape {
public:
   Shape() {
   }
   virtual ~Shape() {
 
   }
 
   const std::string& name() const {
       return m_name;
   }
 
protected:
   std::string m_name;
};
 
//----------------- class Rectangle -------------
class Rectangle : public Shape
{
public:
   Rectangle() {
       m_name = "Rectangle";
   }
};
 
 
//----------------- class Circle -------------
class Circle : public Shape
{
public:
   Circle() {
       m_name = "Circle";
   }
};
 
//----------------- class Viewer -------------
class Viewer {
public:
   void addForPaiting(std::shared_ptr<Shape> pshape) {
       m_pshapes.push_back(pshape);
   }
 
   void showShapes() const {
       for (std::size_t i = 0; i < m_pshapes.size(); ++i) {
           std::cout << "Name of the Shape: " << m_pshapes[i]->name() << std::endl;
       }
   }
 
private:
   std::vector<std::shared_ptr<Shape> > m_pshapes;
};
 
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
 
   std::shared_ptr<Shape> pr(new Rectangle);
   std::shared_ptr<Shape> pc(new Circle);
 
   Viewer viewer;
   viewer.addForPaiting(pr);
   viewer.addForPaiting(pc);
 
   viewer.showShapes();
 
   return a.exec();
}
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #131 : Февраль 27, 2014, 12:32 »

Код
C++ (Qt)
   std::vector<std::pair<int, int> > m_points;
 
Такие сопли надо убирать с помощью typedef, напр
Код
C++ (Qt)
   typedef std::pair<int, int> TPoint;
   typedef std::vector<TPoint> > TVector;
   TVectot m_points;
 

В функции main() я создаю объект класса Viewer и "скармливаю" ему объекты с динамическим типом Rectangle. Я хочу чтобы объект класса Viewer хранил копии объектов Rectangle и др. для перерисовывания. Хранить копии объектов нужно для функции paintGL(), которая вызывается, когда объект нужно перерисовать.
Ну конечно бред собачий - но это неизбежно при любом самостоятельном проектировании Улыбающийся "Хранить копии объектов" - не лезет ни в какие ворота. Простой. хороший и очень популярный способ - viewer знает контейнер УКАЗАТЕЛЕЙ на базовый класс Shape и может вызвать виртуальный draw для каждого из них. Тогда правда неясно что делает массив(ы) точек.

Но этот подход - не единственный, а иногда и не лучший. Напр задача не просто рисовать OpenGL, но и кешировать данные рисования в карте (VBO). Тогда может ставить вопрос так:

- каждая фигура умеет создавать свои "данные рисования" (напр массив точек) которые хранятся вьюером умеющим их отображать. Это конечно совсем не "копии объектов". Заметим что придется попотеть с такими данными для такого "простейшего" объекта как Circle.

Да, и вот если бы у Вас был шейп Polygon - возможно и возникла бы идея метода Convert2Polygon. А так мало кода - много измышлений  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #132 : Февраль 27, 2014, 13:31 »

Посмотрите, пожалуйста, мой маленький демонстрационный пример. Корректно ли я работаю с умными указателями:
Добавьте отладочный вывод в конструкторы и деструкторы фигур и все увидите. Улыбающийся
Учитесь проверять самостоятельно, придумывайте как что можно проверить, иначе вы всегда будете за кем то ходить и спрашивать правильно или нет. Подмигивающий
Записан
8Observer8
Гость
« Ответ #133 : Февраль 27, 2014, 14:19 »

Код
C++ (Qt)
   std::vector<std::pair<int, int> > m_points;
 
Такие сопли надо убирать с помощью typedef, напр
Код
C++ (Qt)
   typedef std::pair<int, int> TPoint;
   typedef std::vector<TPoint> > TVector;
   TVectot m_points;
 

Да, точно! Большое спасибо! Улыбающийся

может вызвать виртуальный draw для каждого из них.

Почему-то все примеры с фигурами (для демонстрации полиморфизма) содержат чисто виртуальную функцию draw(). Но я до сих пор не могу понять, как это реализовать на простейшем примере, используя QGLWidget. Я вижу только один выход - каждый объект статического типа Shape хранит в себе массив точек.

Заметим что придется попотеть с такими данными для такого "простейшего" объекта как Circle.

Circle - это многоугольник с бессконечным количеством вершин. К примеру, можно ограничиться шестиугольником Улыбающийся

Да, и вот если бы у Вас был шейп Polygon - возможно и возникла бы идея метода Convert2Polygon. А так мало кода - много измышлений  Улыбающийся

Polygon - это слишком сложно. Я не знаю, как считать площать многоугольника. Тут интеграл, наверное, нужен.

Посмотрите, пожалуйста, мой маленький демонстрационный пример. Корректно ли я работаю с умными указателями:
Добавьте отладочный вывод в конструкторы и деструкторы фигур и все увидите. Улыбающийся
Учитесь проверять самостоятельно, придумывайте как что можно проверить, иначе вы всегда будете за кем то ходить и спрашивать правильно или нет. Подмигивающий

Ошибок там нет. Во всяком случае, компилируется и выводит результат. Я просто хотел убедиться, что правильно применил shared_ptr Улыбающийся
« Последнее редактирование: Февраль 27, 2014, 14:23 от 8Observer8 » Записан
8Observer8
Гость
« Ответ #134 : Февраль 27, 2014, 14:47 »

"Хранить копии объектов" - не лезет ни в какие ворота. Простой. хороший и очень популярный способ - viewer знает контейнер УКАЗАТЕЛЕЙ на базовый класс Shape

Я боялся, что кто-нибудь удалит объекты и viewer крякнет. Я не знаю, как бы я выкрутился без shared_ptr
Записан
Страниц: 1 ... 7 8 [9] 10 11 ... 13   Вверх
  Печать  
 
Перейти в:  


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