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

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

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

Ура-а-а! Рисует! Веселый



Скажите, пожалуйста, как можно развить ООП дальше в этом примере с фигурами? У меня есть идея сделать Rectangle шаблоном. Ведь для вывода на экран нужны целые значения и в тоже время хочется иметь возможность считать площадь в вещественном виде. Хотя... всё равно неявно из double в int преобразуется (для функций рисования). Просто для практики попробую.

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

main.cpp
Код
C++ (Qt)
#include <QApplication>
#include "shape.h"
#include "rectangle.h"
#include "viewer.h"
#include <utility>
#include <iostream>
#include <memory>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   Viewer viewer;
   viewer.resize(400, 200);
 
   std::shared_ptr<myShapes::Shape> pr1(new myShapes::Rectangle(100.0, 25.0));
   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> pr4(new myShapes::Rectangle(100.0, 25.0));
 
   viewer.addForPainting(pr1);
   viewer.addForPainting(pr2);
   viewer.addForPainting(pr3);
   viewer.addForPainting(pr4);
 
   viewer.show();
   return a.exec();
}
 

viewer.h
Код
C++ (Qt)
#ifndef VIEWER_H
#define VIEWER_H
 
#include <QGLWidget>
#include "shape.h"
 
#include <vector>
#include <memory>
 
class Viewer : public QGLWidget
{
public:
   Viewer(QWidget *pwgt = 0);
 
   void addForPainting(std::shared_ptr<myShapes::Shape> ps) {
       m_pshapes.push_back(ps);
   }
 
protected:
   virtual void initializeGL();
   virtual void resizeGL(int nWidth, int nHeight);
   virtual void paintGL();
 
private:
   std::vector<std::shared_ptr<myShapes::Shape> > m_pshapes;
   void draw(std::shared_ptr<myShapes::Shape> ps, int xOffset, int yOffset);
};
 
#endif // VIEWER_H
 

viewer.cpp
Код
C++ (Qt)
#include "viewer.h"
#include <utility>
#include <QDebug>
 
Viewer::Viewer(QWidget* pwgt) :
   QGLWidget(pwgt)
{
}
 
void Viewer::draw(std::shared_ptr<myShapes::Shape> ps, int xOffset, int yOffset)
{
   glPointSize(2.0);
   glBegin(GL_LINE_LOOP);
   glColor3f(0.0, 0.0, 0.0);
   for (int i = 0; i < ps->amountOfPoints(); ++i) {
       std::pair<int, int> point = ps->point(i);
//        qDebug() << "x = " << point.first << "; xOffset = " << xOffset;
//        qDebug() << "y = " << point.second << "; yOffset = " << yOffset;
       int x = point.first + xOffset;
       int y = point.second + yOffset;
       glVertex2f(x, y);
   }
//    qDebug() << "";
   glEnd();
}
 
/*virtual*/ void Viewer::initializeGL()
{
   qglClearColor(Qt::white);
}
 
/*virtual*/ void Viewer::resizeGL(int nWidth, int nHeight)
{
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glViewport(0, 0, (GLint)nWidth, (GLint)nHeight);
   glOrtho(0, 400, 200, 0, -1, 1);
}
 
/*virtual*/ void Viewer::paintGL()
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   int xGeneralOffset = 50;
   int yGeneralOffset = 100;
   int xOffset = 0;
   int yOffset = 0;
   for (std::size_t i = 0; i < m_pshapes.size(); ++i) {
       if (( (i+1) % 2) != 0) { // Odd, one-based
           xOffset = xGeneralOffset;
           yOffset += yGeneralOffset;
       } else {
           xOffset = xGeneralOffset + 150;
       }
       if (i == 0 || i == 1) {
           yOffset = 50;
       }
       draw(m_pshapes[i], xOffset, yOffset);
   }
}
 

rectangle.h
Код
C++ (Qt)
#ifndef RECTANGLE_H
#define RECTANGLE_H
 
#include "shape.h"
 
namespace myShapes {
 
class Rectangle : public Shape
{
public:
 
   Rectangle(double width = 0.0, double height = 0.0) :
       m_height(height),
       m_width(width)
   {
       addPoint(0, 0);
       addPoint(width, 0);
       addPoint(width, height);
       addPoint(0, height);
   }
 
   static double perimeter(double height, double width) {
       return 2.0 * (height + width);
   }
 
   static double area(double height, double width) {
       return height * width;
   }
 
   virtual double perimeter() const {
       return perimeter(m_height, m_width);
   }
 
   virtual double area() const {
       return area(m_height, m_width);
   }
 
   inline double height() const {
       return m_height;
   }
 
   inline double width() const {
       return m_width;
   }
 
   inline void setHeight(double height) {
       m_height = height;
   }
 
   inline void setWidth(double width) {
       m_width = width;
   }
 
private:
   double m_height;
   double m_width;
};
 
}
 
#endif // RECTANGLE_H
 

shape.h
Код
C++ (Qt)
#ifndef SHAPE_H
#define SHAPE_H
 
#include <vector>
#include <utility>
 
namespace myShapes {
 
class Shape
{
public:
 
   Shape() {
   }
 
   virtual ~Shape() {
   }
 
   virtual double perimeter() const = 0;
   virtual double area() const = 0;
 
   inline void setPoinstSize(int pointSize = 2) {
       m_pointSize = pointSize;
   }
 
   inline int pointSize() const {
       return m_pointSize;
   }
 
   std::pair<int, int> point(int index) const {
       return m_points[index];
   }
 
   int amountOfPoints() {
       return m_points.size();
   }
 
protected:
   void addPoint(int x, int y) {
       m_points.push_back(std::make_pair(x, y));
   }
 
private:
   int m_pointSize;
   std::vector<std::pair<int, int> > m_points;
};
 
}
 
#endif // SHAPE_H
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Скажите, пожалуйста, как можно развить ООП дальше в этом примере с фигурами?

У меня есть идея сделать Rectangle шаблоном.
Пока все это напоминает дамскую прогулку
Цитировать
Полторы мили пешком, назад в коляске
Сделал аж Rectangle - ну вот и типа "освоил". А делать тот же Circle - та ну его, "мы устали". Код почистить тоже времени нет, тут же такие вкусные плюшечки ("умные" указатели и.т.п). Да и вообще, черновая работа не для нас, мы будем "обобщать" (с помощью шаблонов и др пакостей).

Плохо, очень плохо  Плачущий
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



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

(с помощью шаблонов и др пакостей).
Ну да, шаблоны вы тоже не осилили... Улыбающийся

Вы не знаете и половины языка, на котором пишете, вот это действительно:
Плохо, очень плохо

А человек только начал разбираться, у него все еще впереди. Хотя задачи он ставит себе очень синтетические, но не вы ли ему предложили этот идиотизм? Подмигивающий
Записан
8Observer8
Гость
« Ответ #138 : Февраль 28, 2014, 07:59 »

Igors, это неокончательный вариант кода, а всего лишь черновик. Я его ещё буду улучшать.

Сейчас разбираюсь с шаблонами. Начал переписывать и разбирать код из этого правила: http://www.e-reading.bz/chapter.php/1002058/108/Mayers_-_Effektivnoe_ispolzovanie_CPP.html

Вроде сначала всё было понятно, а теперь запутался и ошибки не знаю, как исправить. Если несложно, скомпилируйте, пожалуйста, у себя:

Код
C++ (Qt)
#include <QCoreApplication>
#include <string>
#include <iostream>
 
//---------------------------------------------------------------
class CompanyA {
public:
   // ...
   void sendClearText(const std::string& msg);
   void sendEncryptedText(const std::string& msg);
   // ...
};
 
void CompanyA::sendClearText(const std::string& msg) {
   std::cout << "sendClearText of CompanyA: " << msg << std::endl;
}
 
void CompanyA::sendEncryptedText(const std::string& msg) {
   std::cout << "sendEncryptedText of CompanyA: " << msg << std::endl;
}
 
//---------------------------------------------------------------
class CompanyB {
public:
   // ...
   void sendClearText(const std::string& msg);
   void sendEncryptedText(const std::string& msg);
   // ...
};
 
void CompanyB::sendClearText(const std::string& msg) {
   std::cout << "sendClearText of CompanyB: " << msg << std::endl;
}
 
void CompanyB::sendEncryptedText(const std::string& msg) {
   std::cout << "sendEncryptedText of CompanyB: " << msg << std::endl;
}
 
//---------------------------------------------------------------
// этот класс не представляет функции sendCleartext
class CompanyZ {
public:
   // ...
   void sendEncrypted(const std::string& msg);
   // ...
};
 
void CompanyZ::sendEncrypted(const std::string& msg) {
   std::cout << "sendEncryptedText of CompanyZ: " << msg << std::endl;
}
 
//---------------------------------------------------------------
// полная специализация MsgSender; отличается от общего шаблона
// только отсутствием функции sendCleartext
template <>
class MsgSender<CompanyZ> {
public:
   // ...
   void sendSecret(const MsgInfo& info)
   {
       std::string msg;
       // создать msg из info
       msg = info.msg + " " + msg;
       CompanyZ c;
       c.sendEncrypted(msg);
   }
};
 
//---------------------------------------------------------------
// классы для других компаний
// ...
 
//---------------------------------------------------------------
// класс, содержащий информацию, используемую для создания сообщения
class MsgInfo {
public:
   std::string msg;
};
 
//---------------------------------------------------------------
template <typename Company>
class MsgSender {
public:
   // конструктор, деструктор и т. п.
   // ...
 
   void sendClear(const MsgInfo& info)
   {
       std::string msg;
       // создать msg из info
       msg = info.msg + " " + msg;
       Company c;
       c.sendClearText(msg);
   }
 
   // аналогично sendClear, но вызывает c.sendEncrypted(msg)
   void sendSecret(const MsgInfo& info)
   {
       std::string msg;
       // создать msg из info
       // ...
       Company c;
       c.sendEncrypted(msg);
   }
};
 
//---------------------------------------------------------------
template <typename Company>
class LoggingMsgSender: public MsgSender<Company> {
public:
   // второй способ (см. о чём идёт речь ниже)
   // сообщает компилятору о том, что
   // sendClear есть в базовом классе
   //using MsgSender<Company>::sendClear;
   // ...
 
   void sendClearMsg(const MsgInfo& info)
   {
       // записать в протокол перед отправкой;
       std::cout << "It is written in protocol before sending" << std::endl;
 
       // вызвать функцию из базового класса
       // этот код не будет компилироваться, так как в шаблонных классах
       // компилятор не ищет в базовом
       // sendClear(info);
 
       // первый способ: чтобы код компилировался нужно написать:
       this->sendClear(info);
 
       // второй способ: using MsgSender<Company>::sendClear;
       // sendClear(info);
 
       // третий способ: явно указать, что
       // вызываемая функция находится в базовом классе:
       // MsgSender<Company>::sendClear(info);
       // примечание: но этот способ хуже прочих, посколько если
       // вызываемая функция виртуальна, то явная квалификация
       // отключает динамическое связывание.
 
       // записать в протокол после отправки;
       std::cout << "It is written in protocol after sending" << std::endl;
   }
   // ...
};
 
//---------------------------------------------------------------
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
 
   MsgInfo msginfo;
   msginfo.msg = "Heloooo!";
   MsgSender<CompanyA> msgSender;
   msgSender.sendClear(msginfo);
 
   return a.exec();
}
 
Записан
8Observer8
Гость
« Ответ #139 : Февраль 28, 2014, 09:24 »

Я думаю, что проблема в следующем коде, потому что когда я его убираю в комминтарии, то всё работает.

Но я так и не могу понять, что не так в этом коде:

Код
C++ (Qt)
//---------------------------------------------------------------
// полная специализация MsgSender; отличается от общего шаблона
// только отсутствием функции sendCleartext
template <>
class MsgSender<CompanyZ> {
public:
   // ...
   void sendSecret(const MsgInfo& info)
   {
       std::string msg;
       // создать msg из info
       msg = info.msg + " " + msg;
       CompanyZ c;
       c.sendEncrypted(msg);
   }
};
 
Записан
VPS
Гость
« Ответ #140 : Февраль 28, 2014, 10:15 »

Сейчас разбираюсь с шаблонами. Начал переписывать и разбирать код из этого правила: http://www.e-reading.bz/chapter.php/1002058/108/Mayers_-_Effektivnoe_ispolzovanie_CPP.html

Вроде сначала всё было понятно, а теперь запутался и ошибки не знаю, как исправить. Если несложно, скомпилируйте, пожалуйста, у себя

Если у Вас весь код написан в одном файле, то Вы пытаетесь определить полную спецификацию класса раньше, чем шаблон.
Записан
8Observer8
Гость
« Ответ #141 : Февраль 28, 2014, 10:18 »

Если у Вас весь код написан в одном файле, то Вы пытаетесь определить полную спецификацию класса раньше, чем шаблон.

Да, точно! Спасибо огромное! Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Ну да, шаблоны вы тоже не осилили... Улыбающийся

Вы не знаете и половины языка, на котором пишете,
Ну чего Вы склочничаете когда Вас никто не трогал? Улыбающийся И чего оно Вас так волнует сколько я знаю? Улыбающийся

Igors, это неокончательный вариант кода, а всего лишь черновик. Я его ещё буду улучшать.
Книга что Вы штудируете интересна, но обратите внимание на слова улучшить структуру. Так вот сначала надо уметь создать хоть какую-то структуру. Этого умения у Вас пока нет, зато охотно впитываете вещи которые, по существу, требуют механического запоминания - но не принятия своих решений. Пусть вещи эти совсем неплохи - но главного они не заменят. К сожалению, эта ситуация очень типична, часто смотрю текст - ни классов, ни ф-ционала, ничего по уму нет, "зато" шаблонов навернул с 3 короба. Типа "больше всякой всячины" = лучше, мол, "хорошо знает язык"  Улыбающийся Плачущий
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



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

И чего оно Вас так волнует сколько я знаю?
Так вы же постоянно пытаетесь судить о том, что не знание: шаблоны, пространства имён, стандартная библиотека, и пытаетесь отговорить людей это изучать. Улыбающийся
Но, если вы это не осилили это не значит , что никто не осилить. В основной массе специалисты спокойно используют все возможности С++.
Записан
8Observer8
Гость
« Ответ #144 : Февраль 28, 2014, 12:34 »

Объяните, пожалуйста, почему n = 10?



Проект: https://github.com/8Observer8/Shapes/tree/drawingShapes
« Последнее редактирование: Февраль 28, 2014, 12:36 от 8Observer8 » Записан
8Observer8
Гость
« Ответ #145 : Февраль 28, 2014, 13:06 »

Всё, исправил ошибку: в меню выбрал Build -> Clean Project "Shapes" -> Build -> Rebuild Project "Shapes"

« Последнее редактирование: Февраль 28, 2014, 13:08 от 8Observer8 » Записан
VPS
Гость
« Ответ #146 : Февраль 28, 2014, 13:25 »

Маленький комментарий к коду: вместо использования "new" при создании "std::shared_ptr", вроде как рекомендуют использовать "std::make_shared".

П.С.: только эта функция не позволяет задавать пользовательскую операцию удаления.
« Последнее редактирование: Февраль 28, 2014, 13:28 от vps » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

И что, если клиент вызывает Circle::setRadius - продолжает рисоваться старый?
Записан
8Observer8
Гость
« Ответ #148 : Февраль 28, 2014, 18:32 »

И что, если клиент вызывает Circle::setRadius - продолжает рисоваться старый?

Новый должен рисоваться. Вот только почему-то компилятор ищет имя "setRadius" в базовом классе. Ошибка такая:

Цитировать
Shapes\main.cpp:31: error: 'class myShapes::Shape' has no member named 'setRadius'
     pc->setRadius(25.0);
           ^

На строке: pc->setRadius(25.0);

Код
C++ (Qt)
#include <QApplication>
#include "shape.h"
#include "rectangle.h"
#include "circle.h"
#include "triangle.h"
#include "viewer.h"
#include <memory>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   Viewer viewer;
   viewer.resize(400, 200);
 
   std::shared_ptr<myShapes::Shape> pt(new myShapes::Triangle(30.0, 50.0));
   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> 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();
}
 
« Последнее редактирование: Февраль 28, 2014, 18:33 от 8Observer8 » Записан
Johnik
Крякер
****
Offline Offline

Сообщений: 339


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

Потому как базовый класс Shape не знает метода setRadius()
Записан
Страниц: 1 ... 8 9 [10] 11 12 13   Вверх
  Печать  
 
Перейти в:  


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