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

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

Страниц: [1] 2 3 ... 13   Вниз
  Печать  
Автор Тема: Как писать ООП программы?  (Прочитано 86585 раз)
8Observer8
Гость
« : Февраль 16, 2014, 08:14 »

Привет!

Расскажите о своём подходе к созданию ООП программ. С чего вы начинаете разработку? Какими инструментами пользуетесь для построения диаграмм? В каких случаях используете виртуальные функции и полиморфизм?

Если все используют UML, то подскажите: где скачать? как использовать? И дайте, пожалуйста, ссылку на простой и доступный туториал Улыбающийся

Допустим мне нужно создать игру. Как определиться с требованиями? Как построить архитектуру? Пусть она будет текстовая-консольная (у меня нет сил осваивать OpenGL)

За основу я возьму проект из каталога examples/json/savegame Там следующие классы:

game.h
Код
C++ (Qt)
#ifndef GAME_H
#define GAME_H
 
#include <QJsonObject>
#include <QList>
 
#include "character.h"
#include "level.h"
 
//! [0]
class Game
{
public:
   Game();
 
   enum SaveFormat {
       Json, Binary
   };
 
   const Character &player() const;
   const QList<Level> &levels() const;
 
   void newGame();
   bool loadGame(SaveFormat saveFormat);
   bool saveGame(SaveFormat saveFormat) const;
 
   void read(const QJsonObject &json);
   void write(QJsonObject &json) const;
private:
   Character mPlayer;
   QList<Level> mLevels;
};
//! [0]
 
#endif // GAME_H
 

character.h
Код
C++ (Qt)
#ifndef CHARACTER_H
#define CHARACTER_H
 
#include <QJsonObject>
#include <QString>
 
//! [0]
class Character
{
public:
   enum ClassType {
       Warrior, Mage, Archer
   };
 
   Character();
   Character(const QString &name, int level, ClassType classType);
 
   QString name() const;
   void setName(const QString &name);
 
   int level() const;
   void setLevel(int level);
 
   ClassType classType() const;
   void setClassType(ClassType classType);
 
   void read(const QJsonObject &json);
   void write(QJsonObject &json) const;
private:
   QString mName;
   int mLevel;
   ClassType mClassType;
};
//! [0]
 
#endif // CHARACTER_H
 

level.h
Код
C++ (Qt)
#ifndef LEVEL_H
#define LEVEL_H
 
#include <QJsonObject>
#include <QList>
 
#include "character.h"
 
//! [0]
class Level
{
public:
   Level();
 
   const QList<Character> &npcs() const;
   void setNpcs(const QList<Character> &npcs);
 
   void read(const QJsonObject &json);
   void write(QJsonObject &json) const;
private:
   QList<Character> mNpcs;
};
//! [0]
 
#endif // LEVEL_H
 

main.cpp
Код
C++ (Qt)
#include <QCoreApplication>
 
#include "game.h"
//! [0]
int main(int argc, char *argv[])
{
   QCoreApplication app(argc, argv);
 
   Game game;
   game.newGame();
   // Game is played; changes are made...
//! [0]
//! [1]
   if (!game.saveGame(Game::Json))
       return 1;
 
   if (!game.saveGame(Game::Binary))
       return 1;
 
   Game fromJsonGame;
   if (!fromJsonGame.loadGame(Game::Json))
       return 1;
 
   Game fromBinaryGame;
   if (!fromBinaryGame.loadGame(Game::Binary))
       return 1;
 
   return 0;
}
//! [1]
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



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

Если вы по настоящему хотите с этим разобраться, то эту книгу нужно почитать обязательно:
Гради Буч - Объектно-ориентированный анализ и проектирование с примерами приложений.
« Последнее редактирование: Февраль 16, 2014, 08:41 от Old » Записан
8Observer8
Гость
« Ответ #2 : Февраль 16, 2014, 10:01 »

Спасибо большое! Начал изучать.

Почитал на ozon.ru отзывы: http://www.ozon.ru/context/detail/id/3905587/#tab_comments

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

Перевод: http://rutracker.org/forum/viewtopic.php?t=3343958
Оригинал: http://kickass.to/object-oriented-analysis-and-design-with-applications-3rd-editio-t2753820.html

Прилагаются ли к книге какие-нибудь дополнительные материалы (например, исходники или\и файлы UML)? Обычно исходники в отдельную папку помещают и их можно откуда-нибудь скачать.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



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

Прилагаются ли к книге какие-нибудь дополнительные материалы (например, исходники или\и файлы UML)?
Нет. Это фундаментальный труд, компилируемых примеров в нем нет. Зато на примерах разбирается как же нужно думать, что бы проектировать ОО-программы.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Расскажите о своём подходе к созданию ООП программ. С чего вы начинаете разработку? Какими инструментами пользуетесь для построения диаграмм? В каких случаях используете виртуальные функции и полиморфизм?
- Не думаю что надо разделять программы на "ООП и нет".

- Диаграммы - не знаю точно что Вы имеете ввиду. Часто использую гистограммы (обычно просто печать в консоли), иногда графики. А чаще всего сливаю линии/точки (иногда раскрашенные) в текстовик и визуализирую это в 3D.

- виртуалы и.т.п. Все это цветет пышным цветом в UI, в расчетной части иерархия классов может быть очень небольшой и "конкретные" классы могут доминировать. Зато часто нужен гораздо более тщательный выбор структур данных и контейнеров.

С чего начинать разработку. С четкого понимания "кому это нужно". Можно сказать и "кому это можно продать" - не вижу в этом ничего плохого. Пройдет какое-то время и любой энтузиазм угаснет, это нормально, запас энергии человека ограничен. Поэтому надо прикинуть - а что я успею сделать "на первой волне", пока мне (еще) интересно этим заниматься. Сумею ли достичь каких-то пусть промежуточных но реальных результатов? Потому что неоплачиваемый проект долго не протянет. А учитывая еще что Вы делаете массу др дел .. Улыбающийся

В общем до пресловутой "архитектуры" еще очень далеко. Сначала ТЕМУ/задачу выберите тщательно, пока у меня впечатление что для Вас это дело десятое, типа "что угодно лишь бы опыта набраться". Это не вредно, но и пользы не много.
Записан
8Observer8
Гость
« Ответ #5 : Февраль 17, 2014, 15:40 »

Диаграммы - не знаю точно что Вы имеете ввиду. Часто использую гистограммы (обычно просто печать в консоли), иногда графики. А чаще всего сливаю линии/точки (иногда раскрашенные) в текстовик и визуализирую это в 3D.

Я имею ввиду диаграммы наследования. А Вы?

виртуалы и.т.п. Все это цветет пышным цветом в UI

А на примере проекта "savegame" (о котором я написал вначале) можно же поиграть с наследованием, полиморфизмом, виртуальными функциями? Как мне развивать этот проект (консольная игра), чтобы я видел, что мне действительно улучшает жизнь полиморфизм (и т.д.)? Я хочу на этом живом примере применить ООП в полной мере! Мне нужны идеи именно по этому проекту. Я думаю, что разработка простой игры - это как раз то, что нужно для тренировки ООП. Но у меня в этом проекте полный тупик. Я буду рад любым идеям по его развитию (с точки зрения применения всех аспектов ООП).

Вот тут создаётся этот персонаж (за которого мы будем играть). Как мне заставить его ходить? Создаётся так же несколько неигровых персонажей (NPS) на разных локациях (этот пример расположен в папке Qt examples/json/savegame):

Код
C++ (Qt)
void Game::newGame() {
   mPlayer = Character();
   mPlayer.setName(QStringLiteral("Hero"));
   mPlayer.setClassType(Character::Archer);
   mPlayer.setLevel(15);
 
   mLevels.clear();
 
   Level village;
   QList<Character> villageNpcs;
   villageNpcs.append(Character(QStringLiteral("Barry the Blacksmith"), 10, Character::Warrior));
   villageNpcs.append(Character(QStringLiteral("Terry the Trader"), 10, Character::Warrior));
   village.setNpcs(villageNpcs);
   mLevels.append(village);
 
   Level dungeon;
   QList<Character> dungeonNpcs;
   dungeonNpcs.append(Character(QStringLiteral("Eric the Evil"), 20, Character::Mage));
   dungeonNpcs.append(Character(QStringLiteral("Eric's Sidekick #1"), 5, Character::Warrior));
   dungeonNpcs.append(Character(QStringLiteral("Eric's Sidekick #2"), 5, Character::Warrior));
   dungeon.setNpcs(dungeonNpcs);
   mLevels.append(dungeon);
}
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Я имею ввиду диаграммы наследования. А Вы?
Если они есть в ID - иногда смотрю (редко). А нет - прекрасно обхожусь без них.

А на примере проекта "savegame" (о котором я написал вначале) можно же поиграть с наследованием, полиморфизмом, виртуальными функциями? Как мне развивать этот проект (консольная игра), чтобы я видел, что мне действительно улучшает жизнь полиморфизм (и т.д.)? Я хочу на этом живом примере применить ООП в полной мере! Мне нужны идеи именно по этому проекту. Я думаю, что разработка простой игры - это как раз то, что нужно для тренировки ООП.
Я так не думаю. Фрагмент кода что Вы показали - это уже манипуляции "верхнего уровня", когда все готово/выписано и этим надо рулить. ООП здесь ни при чем. Конечно можно поиграться с этим примером - но на этом дело и кончится.

Вообще примеры - палка о двух концах. Создается впечатление что все довольно "просто" и даже "элементарно" - но смогли бы Вы сделать все это "с нуля"? Да, Вы узнаете много нового, но также и "попадаете под влияние" могучих троллей, и в этом есть свои минусы. Вот относительно недавно тут паренек писал свой морской бой с нуля - мне кажется такой подход лучше. Задумка должна быть своя, а идей "простой" игры предостаточно

Возвращаясь к ООП - вряд ли игровой проект может служить для его тренировки. Есть пример ООП наследования который приводится с незапамятных времен: фигуры. Напр есть базовый класс Shape, от него наследуется Circle, Triangle и.т.п. Аналогичный пример есть в Qt (кажется демонстрация undo, точно не помню). Хоть и не игра - но для освоения ООП подойдет гораздо лучше
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



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

Возвращаясь к ООП - вряд ли игровой проект может служить для его тренировки.
Конечно может и очень хорошей. А написание своего рогалика, так вообще замечательная идея.
В нем очень много объектов разных классов, которые должны взаимодействовать друг с другом.

А пример с фигурами... Это для детского сада.
Записан
Bepec
Гость
« Ответ #8 : Февраль 17, 2014, 17:34 »

На мой взгляд только игра и способствует развитию ООП мышления. Ибо в играх обычно приводится реальный мир с его разнообразием объектов. Всё под рукой Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

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

А вот кстати сегодняшний пример наследования http://www.prog.org.ru/index.php?topic=26553.msg190549#msg190549 Что Вы о нем думаете? 

Old, просьба не спешить, пусть сначала товарищи выскажутся  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



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

С чем-то более сложным - боюсь все уйдет в изучение того что уже сделано (готовых классов), и на изобретение чего-то своего ничего не останется
А в своем рогалике нет готовых классов, там все нужно делать с нуля. Вообще все. Улыбающийся
Нечего изучать, можно только делать. А текстовый интерфейс не дает уйти в создание красивых эффектов вместо хорошего геймплея.
Записан
8Observer8
Гость
« Ответ #11 : Февраль 18, 2014, 15:26 »

Всем большое спасибо! Начну с простого.

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

Примеры будут на Qt и на C++, чтобы меня не ругали, что это форум Qt, а не C++.

Рациональные числа

Примечание. Пример взял отсюда: http://www.e-reading.co.uk/chapter.php/1002058/56/Mayers_-_Effektivnoe_ispolzovanie_CPP.html

В примере затронуты следующие темы:

- список инициализации в конструкторе
- дружественные функции
- перезагрузка операторов: умножения, сложения и вычитания.

Какие ещё операторы посоветуете перезагрузить? Как дальше доработать этот класс?

Примечание. При сложении и вычитании дробей: к общему знаменателю привожу - перемножением, результат не сокращаю.

Вывод:
product = 6/24
sum = 1472/768
sub = 32/768

main.cpp
Код
C++ (Qt)
#include <QCoreApplication>
#include <QTextStream>
#include "rational.h"
 
QTextStream cin(stdin);
QTextStream cout(stdout);
 
int main(int argc, char *argv[])
{
   QCoreApplication app(argc, argv);
 
   // Перемножаем дроби и выводим результат на экран
   Rational a(2, 3), b(1, 2), c(3, 4), product;
   product = a * b * c;
   cout << "product = " << product.numerator() << "/" << product.denominator() << endl;
   cout.flush();
 
   // Складываем дроби и выводим результат на экран
   Rational x(47, 48), y(15, 16), sum;
   sum = x + y;
   cout << "sum = " << sum.numerator() << "/" << sum.denominator() << endl;
   cout.flush();
 
   // Вычитаем дроби и выводим результат на экран
   Rational m(47, 48), n(15, 16), sub;
   sub = m - n;
   cout << "sub = " << sub.numerator() << "/" << sub.denominator() << endl;
   cout.flush();
 
   return app.exec();
}
 

rational.h
Код
C++ (Qt)
#ifndef RATIONAL_H
#define RATIONAL_H
 
class Rational
{
public:
   Rational(int numerator = 0, int denominator = 1);
 
   int numerator() const;
   void setNumerator(const int numerator);
 
   int denominator() const;
   void setDenominator(const int denominator);
 
   friend const Rational operator*(const Rational& lhs, const Rational& rhs);
   friend const Rational operator+(const Rational& lhs, const Rational& rhs);
   friend const Rational operator-(const Rational& lhs, const Rational& rhs);
 
private:
   int mNumerator;
   int mDenominator;
};
 
#endif // RATIONAL_H
 

rational.cpp
Код
C++ (Qt)
#include "rational.h"
 
Rational::Rational(int numerator, int denominator) :
   mNumerator(numerator),
   mDenominator(denominator)
{
}
 
int Rational::numerator() const
{
   return mNumerator;
}
 
void Rational::setNumerator(const int numerator)
{
   mNumerator = numerator;
}
 
int Rational::denominator() const
{
   return mDenominator;
}
 
void Rational::setDenominator(const int denominator)
{
   mDenominator = denominator;
}
 
const Rational operator*(const Rational &lhs, const Rational &rhs)
{
   return Rational(lhs.mNumerator * rhs.mNumerator,
                   lhs.mDenominator * rhs.mDenominator);
}
 
const Rational operator+(const Rational &lhs, const Rational &rhs)
{
   Rational result;
 
   // Общий знаменатель
   int commonDenominator = lhs.denominator() * rhs.denominator();
 
   // Числитель
   int a = lhs.numerator() * rhs.denominator();
   int b = rhs.numerator() * lhs.denominator();
   result.setNumerator(a + b);
 
   // Знаменатель
   result.setDenominator(commonDenominator);
 
   return result;
}
 
const Rational operator-(const Rational &lhs, const Rational &rhs)
{
   Rational result;
 
   // Общий знаменатель
   int commonDenominator = lhs.denominator() * rhs.denominator();
 
   // Числитель
   int a = lhs.numerator() * rhs.denominator();
   int b = rhs.numerator() * lhs.denominator();
   result.setNumerator(a - b);
 
   // Знаменатель
   result.setDenominator(commonDenominator);
 
   return result;
}
 
Записан
Bepec
Гость
« Ответ #12 : Февраль 18, 2014, 15:54 »

Походу все темы можно в говорилку отправлять Веселый
PS я не имею в виду, что они флуд. Но к вопросам они явно не относятся Веселый
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



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

Цитировать
Примечание. При сложении и вычитании дробей: к общему знаменателю привожу - перемножением, результат не сокращаю.

Это плохо(
Во-вторых, хотелось бы иметь операторы сравнения..
И такие, чтобы, например, 4/2 и 10/5 получались  равными друг другу)

И ещё я бы посмотрел на Compile-time rational arithmetic http://en.cppreference.com/w/cpp/numeric/ratio
« Последнее редактирование: Февраль 18, 2014, 16:00 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Примеры будут на Qt и на C++, чтобы меня не ругали, что это форум Qt, а не C++.
Ну так Вас забросают помидорами, скажут что "занимаетесь фигней" - и, в общем, это будет правильно  Улыбающийся. Вы бросились в др крайность - слишком просто, нет достойного обсуждения предмета. "Отдельно стоящий класс" можно разрисовать как угодно красиво, но столь же бесполезно - потому что нет никаких связок/взаимодействий классов.

Подкинуть идей - ну так, наскидку, трудновато. Впрочем один я уже подкинул (с тенью окна, см выше). Хорошо, вот еще

- в классическом примере с фигурами утверждается что "каждая фигура умеет себя рисовать", это полиморфный метод. Какие недостатки у такого решения? Так ли уж оно бесспорно? Можно ли привести пример когда оно оказывается неудачным?
Записан
Страниц: [1] 2 3 ... 13   Вверх
  Печать  
 
Перейти в:  


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