Помощь - Поиск - Пользователи - Календарь
Полная версия: классы,работа с геометрическими объектами.
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
Tribunal
Задание следующее:
Написать программу,демонстрирующую работу с объектами двух типов Т1 и Т2,для чего создать систему соответствующих классов. Каждый объект должен иметь идентификатор(в виде произвольной строки символов) и одно или несколько полей для хранения состояния (текущего значения) объекта.
Клиенту(ф-ии main) должны быть доступны следующеие основные операции(методы):создать объект,удалить объект,показать значение объекта и прочие дополнительные операции,которые будут указаны ниже.Операции по созданию и удалению объектов инкапсулировать в классе Factory.Предусмотреть место,позволяющее продемонстрировать заданные операции.
При необходимости в разрабатываемые классы добавляются дополнительные методы(например,конструктор копирования,операция присваивания и тп)для обеспечения надлежащего функционирования этих классов.

Типы объектов
Класс \ Объект
-------------------------------------------------
Triangle \ Треугольник
Quadrate \ Квадрат
Rectangle \ Прямоуголник
Tetragon \ Четырёхуголник
Pentagon Пятиугольник

Перечень дополнительных операций
Операция(метод) \ Описание
-------------------------------------------------------------
Move() \ Переместить объект на плоскости
Compare(T& ob1,T& ob2) \ Сравнить объект 1 и 2 по площади
IsIntersect(T& ob1,T& ob2) \ Определить факт пересечения объектов 1,2(есть\нет)
IsInclude(T& ob1,T& ob2) \ Определить факт включения объекта 2 в объект 1.

T1 \ T2 \ Операция(Метод)
----------------------------------------------
Triangle \ Pentagon \ Move(),Compare(T&,T&)



дык вот....я даже не знаю с чего начать...
помогите,пожалуйста.
Алена
Цитата
дык вот....я даже не знаю с чего начать...
Начни с построения иерархии с "заглушками" - пустыми методами, или методами, только печатающими, какие действия они должны производить:


#include "iostream.h"

// Базовый класс для всех фигур, чтобы были возможны, например,
// операции сравнения площади в любых вариантах
class TFigure {

public:
TFigure(const char *s = ""): name(s) {
cout << name << " created ..." << endl;
}

// чисто виртуальный метод, вычисление площади,
// будет переопределяться в каждом производном классе
virtual double getS() const = 0;

protected:
// Название фигуры
const char *name;

};

// Определяем класс - наследник от TFigure
class TTriangle: public TFigure {
public:

// Конструктор... В процессе работы над программой тебе придется
// добавить сюда еще несколько параметров, гарантирующих однозначное
// определение треугольника на плоскости (например, координаты 3-х точек),
// но для начала - "пустышка"
TTriangle() : TFigure("triangle") {
}

// Переопределение метода расчета площади
// (если этого не сделать, то нельзя будет создать экземпляр класса TTriangle,
// т.к. считается, что он содержит неперекрытую ЧИСТО виртуальную функцию)
double getS() const {
return 10.0; // Для простоты будем считать, что ВСЕ треугольники имеют площадь = 10
}

};

class TQuadrate: public TFigure {
public:

// Аналогично, добавить в конструктор необходимые параметры
// для задания квадрата на плоскости
TQuadrate() : TFigure("square") {
}

double getS() const {
return 12.0;
}

};

// Сравнение площадей двух фигур... Возможны любые комбинации, главное,
// чтобы T1 и T2 были потомками (в любом "поколении") TFigure
int Compare(const TFigure &T1, const TFigure &T2) {

// Благодаря виртуальным функциям, вызываются методы getS именно тех классов,
// экземпляры которых переданы как фактические параметры в функцию
return (T1.getS() < T2.getS()) ? -1 : 1;
}


// Основная программа пока умеет немного - только задать один или несколько экземпляров
// одного из вышеопределенных классов ...
int main() {

TTriangle T1;
// ... напечатать площадь этого объекта ...
cout << T1.getS() << endl;

TQuadrate T2;
cout << T2.getS() << endl;

// ... и вывести результат сравнения плохадей в одном порядке ...
cout << Compare(T1, T2) << endl;
// ... и в другом тоже (знаки результатов должны быть противоположными)
cout << Compare(T2, T1) << endl;

return 0;

}

Теперь у тебя есть "основа" программы, и ты можешь добавлять в нее все необходимые функции... Маленький совет: не добавляй все сразу - ни к чему хорошему это не приведет... Например, добавь инициализацию треугольника тремя точками, отработай программу, проверь, что все в порядке, только потом добавляй инициализацию квадрата...

Можешь изменить Compare так, чтобы при одинаковых площадях возвращался 0...

Что не будет получаться - пиши smile.gif
Tribunal
а вот вопросик возник.
когда создаю фигуру,ее создание следует делать по вершинам,так?
есть ли смысл делать структуру ,скажем,ВЕРШИНА для определения координат...
то бишь тогда при задействовании конструктора,надо будет в парметрах написать только названия вершин...
или так нельзя?
и где ее прописывать...за пределами класса или внутри,...тогда какого...
Алена
Цитата
есть ли смысл делать структуру ,скажем,ВЕРШИНА для определения координат...
Есть, конечно... Что же ты хочешь передавать 6 разрозненных координат вместо трех пар? Лучше сделать структуру... Тем более, что используя эту структуру, будет проще, например, определить расстояние между точками... Каждая структура/класс должна заниматься своим делом, а не так, что один класс делает практически все, а остальные - просто для красоты...

Цитата
и где ее прописывать...за пределами класса или внутри
А вот это зависит от того, будет ли твоя структура (TPoint, например) использоваться только в TFigure и наследниках, или планируется ее использование также и в других классах (которые никак не связаны с TFigure)? Если толко для вот этих типов фигур - тогда имеет смысл объявить внутри TFigure (как базового класса):


public: // В секции public, потому что нам понадобится доступ и "снаружи"
struct TPoint {
// Конструктор по умолчанию...
TPoint(int px = 0, int py = 0): x(px), y(py) {
}

int x, y;
};


Это даст тебе возможность сделать, например, так:
class TTriangle: public TFigure {

private:
TPoint *pts; // указатель на массив TPoint, для хранения вершин

public:

TTriangle(TPoint p1, TPoint p2, TPoint p3) :
TFigure("triangle") {

pts = new TPoint[3]; // берем память под массив
... // и заполняем массив вершинами

}
~TTriangle() {
delete [] pts; // не забываем удалять массив
}

double getS() const {
return 10.0;
}

};
, а в main() делать так:

...
TTriangle T1(
TFigure::TPoint(1, 1),
TFigure::TPoint(3, 3),
TFigure::TPoint(5, 5)
);
cout << T1.getS() << endl;
...


Кстати, заметь, что если TPoint описывается внутри класса TFigure, то нужно указывать его области видимости ( TFigure:: ) для того, чтобы компилятор понял, о чем идет речь... Если же ты определить TPoint снаружи - то этого делать будет не нужно... Внутри классов, унаследованных от базового область видимости указывать не нужно...
Tribunal
вот попыталась сделать конструктор...
я хочу,чтобы при обращении к конструктору запрашивались координаты вершин.так можно делать?
что не так?
Код
class TTriangle: public TFigure
{
    private:
    TPoint *pts;
    public:
    TTriangle(TPoint p1,TPoint p2,TPoint p3):TFigure("triangle")
    {
        pts = new TPoint[3];
        for(int i=0;i<3;i++)
        {
            cout << "Enter coordinates of apex" << i+1 << ":";
            cin << TPoint[i].x << TPoint[i].y; //вот здесь ошибку выдаёт
        }
    }

    ~TTriangle()
    {
        delete [] pts;
    }

    double getS() const {
    return 0.5*(TPoint[1].y*TPoint[2].x-TPoint[2].y*TPoint[1].x+TPoint[2].y*TPoint[3].x-
                          TPoint[3].y*TPoint[2].x-TPoint[1].y*TPoint[3].x+TPoint[1].y*TPoint[1].x);;
  }

};


и позже в main компилятор ругается на обращение к конструктору
Код
TTriangle T1;


площадь треульника я вычисляла по половине опредлителя матрицы
1;1;1
x1;x2;x3
y1;y2;y3
а как вычислить площадь пятиугольника.
ведь по моему заданию мне нужно работать именно с треугольником и пятиугольником
Цитата
T1 \ T2 \ Операция(Метод)
----------------------------------------------
Triangle \ Pentagon \ Move(),Compare(T&,T&)
Tribunal
вот то,что у меня получилось.
я не очень разобралась с общими методами для фигур,поэтому программа не компилируется.
посмотрите,пожалуйста.
в чем мои ошибки?
Алена
1) ты забыла одну закрывающую скобку (завершающую в функции TFigure::move_it), и получила несколько наведенных ошибок... Кстати, компилятор предупреждает тебя, что функции, содержащие for не будут inline-функциями, поэтому их описания лучше выносить за пределы определения класса...

2)
double getS() const {
return
0.5*(
TPoint[1].y*TPoint[2].x-TPoint[2].y*TPoint[1].x+
TPoint[2].y*TPoint[3].x-TPoint[3].y*TPoint[2].x-
TPoint[1].y*TPoint[3].x+TPoint[1].y*TPoint[1].x
);
}
это неправильно... Чтобы обращаться к точкам, тебе достаточно:
    double getS() const
{
return 0.5 * (pts[0].y*pts[1].x - pts[1].y*pts[0].x +
pts[1].y*pts[2].x - pts[2].y*pts[1].x -
pts[0].y*pts[2].x + pts[0].y*pts[0].x);
}
- обращаться по имени переменной, а не типа... Причем, заметь, массивы в С++ индексируются с 0 а не с 1... Та же самая ошибка у тебя - при попытке считать координаты точек в конструкторе TPentagon...

3) В классе TPentagon деструктор должен называться ~TPentagon(), а не ~TTriangle()...

4) В классе TPentagon переменная pts не определена в классе, а определена только в конструкторе, т.е. при выходе из конструктора ты все точки потеряешь... Перенеси определение переменной в сам класс...

5) еще одна ощибка - в функции Compare: ты описываешь ее, как возвращающую символ, а пытаешься вернуть строку... Символ - это одиночные апострофы, строка - кавычки... Вот правильное определение:
char Compare(const TFigure &T1, const TFigure &T2)
{
return (T1.getS() < T2.getS()) ? '<' : '>';
}


6) У тебя нет конструктора по умолчанию для TTriangle и для TPentagon. А ты пытаешься его вызвать...
  TTriangle T1;
А вот как от этого избавиться - это уже вопрос к тебе: ты все-таки решила, что хочешь вводить координаты точек прямо в конструкторе? Тогда делай именно конструкторы по умолчанию... Для TTriangle, например, такой:
    TTriangle(int numPoints = 3) : TFigure("triangle")
{
pts = new TPoint[numPoints];
for(int i=0;i<numPoints;i++)
{
TPoint p;
cout << "Enter coordinates of apex" << i+1 << ":";
cin << p.x << p.y;

pts[i] = p;
}
}


7) С show_position ты тоже что-то намудрила, там должна быть либо виртуальная функция (переопределяемая в наследниках), как и в случае с getS(), либо... Хотя нет, ты сделай пока виртуальную, а я тебе потом покажу, как еще можно сделать...

Ну, вроде пока все. Постарайся исправить эти ошибки smile.gif

Это не так сложно, как кажется на первый взгляд, ты же только начинаешь ООП, а это - совершенно другой стиль программирования...
Tribunal
воть...теперь он еще и на ввод-вывод ругается в нескольких местах...почти всех...=(
а если сделать ввод координат вершин вне конструктора,лучше будет?=)
Алена
Смотри, как я переделала классы... Твоя программа стала уже сейчас тяжело читаемой, представляешь, что будет потом?

Нажмите для просмотра прикрепленного файла

smile.gif
Tribunal
огромное спасибо!!! smile.gif smile.gif
сейчас со всем разберусь...
а идеи насчет площади пятиугольника у вас нет?
через определитель длинная формула очень будет)
volvo
Цитата
а идеи насчет площади пятиугольника у вас нет?
Ориентированная площадь вычисляется в 3 строки:
    double getS() const
{
double s = 0;
for(int i = 0; i < ptsAmount; i++) {
int j = (i == (ptsAmount - 1)) ? 0 : (i + 1);

s += (pts[i].x - pts[j].x) * (pts[i].y + pts[j].y);
}
return (0.5 * s);
}
Tribunal
а я с площадью сама разобралась!=)
но всё равно огромное спасибо за вашу помощь=)
Tribunal
в этой программе мне нужно задействовать дружественные функции...
не подскажете,как это можно сделать и с какими функциями?

правда на этот раз мне нужно работать с треугольником и прямоугольником,
а действия призводить над ними:перемещение и проверку пересечения этих фигур.
Tribunal
не могу я понять смысл дружестенных функций...поэтому и не могу реализовать их в программе...=(
помогите ,пожалуйста, разобраться что к чему...
volvo
Дружественная функция?

Как бы объяснить... Ага... Вот так, наверное:
если у тебя описан такой класс (это никак не связано с твоей задачей, просто пример):
class A {
public:
A(int value) {
x = value;
}
private:
int x;
};


и тебе надо сделать вот такую функцию:
int is_equal(const A &first, const A &second) {
// Вернем 1, если поля "х" обоих классов равны, иначе - 0
return (first.x == second.x) ? 1 : 0;
}

, то это работать не будет... Потому, что нет у тебя доступа к "x" извне класса, приватные поля доступны только внутри класса, правда? Так вот это ограничение не распространяется на функции - "друзья", такие функции имеют доступ ко всем членам класса, другом которого они являются... Т.е., если сделать:
class A {
friend int is_equal(const A&, const A&);
public:
A(int value) {
x = value;
}
private:
int x;
};

int is_equal(const A &first, const A &second) {
return (first.x == second.x) ? 1 : 0;
}
, то здесь уже все будет в пределах правил: доступ из "друга" к приватным полям разрешен...
Tribunal
аха...вроде понятно...спасибо большое!=)
а не подскажете,как мне с пересечением справиться(треугольника и прямоугольника)...
я уже и не знаю что с ними делать...координаты сравнивать как-то глупо...с уравнениями прямых тоже нельзя работать...как быть? unsure.gif
Tribunal
а если использовать этот алгоритм для проверки пересечения в оем случае,как лучше поступить с зданием вешин? unsure.gif
Пересечение выпуклых полигонов
volvo
Точка - она и в Африке точка, так что будет работать (если запрограммируешь сам алгоритм правильно) и с таким заданием, как это сделано в сообщении №9... Возиожно придется массив точек заменить на список, или какой-то еще другой класс, но желательно, чтобы все вершины были известны уже в базовом классе...

Кстати, прежде, чем прикручивать этот алгоритм к твоей программе, сделай его отдельно (и прогони хотя бы несколько тестов), убедись что все правильно работает, и только потом перекраивай весь проект, а то начнешь, будет работать неверно - подумаешь, что ошиблась при переделке, потеряешь кучу времени, а это в самом алгоритме недочет какой-нибудь...
Tribunal
в общем я решила сравнивать координаты максимумов и минимумов в зависимости от положения фигур друг относительно друга....
есть проблемы с ф-ией определения min\max...ругается,что непостоянная ф-ия вызывается для постоянного объкта...как этого избжать?
и у меня нет идей,какую ф-ию можно сдлать дружественной...
Tribunal
изменила код выше
Tribunal
воть....как думаете по какой причине можт IsIntersect неправильно результат иногда выдавать?=(
volvo
Приведи пример ввода, на котором выдаются неправильные результаты...
Tribunal
например,
треугольник
0 0
0 5
5 0
прямоугольник
1 1
1 5
5 5
5 1
Tribunal
не помогло даже добавление вроде как необходимого альтернативного варианта включения вершины другой фигуры,ведь первая не обязательно содержит вершины второй,но тогда вторая-обязаельно...
if ((T1->IsInside(T2->pts[i].x,T2->pts[i].y))||(T2->IsInside(T1->pts[i].x,T1->pts[i].y))) {flag=true;break;};
Tribunal
всё)сообразила..всё дело было в типах
Гость
Это задача из учебника Павловской "Объектно-ориентированное программирование. Практикум", стр 102

Препод мне тоже дал эту задачу, причем сдавать мне ее надо сегодня (именно СЕГОДНЯ!!!! через 15 мниут выезжаю). Я даже не расчитывал седня сдать, но благодаря Tribunal`у, Алене, volvo, а также Яндексу и Опере мои планы резко изменилисьsmile.gif))). Как бы сказал мой препод "Радость моя огромна":)))).

В связи в этим хочу выразить искреннюю благодарность всем перечисленным выше лицам (и программам), в особенности Tribunal, за практически готовый исходник программы про треугольники и прямоугольники.


---------------------------
С уважением
Nicolas
Начинающей программер
Извините, а ктонибудь не может немного переписать эту прогу так, чтобы объекты не создавались сами(т.е. автоматически), а чтобы было меню, где можно было бы выбрать создание объекта. И с удалением тоже самое. Сам пробовал, но компилироваться не хочет. Я так понял, что создание прописано в конструкторе. Но ведь конструктор же вызвать нельзя, => надо создание извлеч из конструктора и поместить в дружественную ф-ию, я так понял. Но простое копирование не проходит. Находит много ошибок. Помогите начинающему программеру пожалуйста.
volvo
Цитата
Но простое копирование не проходит. Находит много ошибок.
Показывай, КАК именно пробовал делать (что, куда и откуда копировал)...
Гость
Я использовал последний пример от Tribunal.
Так вот я делал так:
Для создания объекта допустим ф-ия:
TFigure::Great(int numPoints, const char *s = ""):name(s), ptsAmount(numPoints)
{
pts = new TPoint[ptsAmount];
cout << name << " created ..." << endl;
for(int i = 0; i < ptsAmount; i++)
{
TPoint p;
cout << "Enter coordinates of apex" << i+1 << ":";
cin >> p.x >> p.y;
pts[i] = p;
}
}

и для удаления:
TFigure::del(void)
{
TFigure;
}
Понимаю, что что то надо изменить, но не знаю что. И в таком случае, если эти ф-ии будут как дружественные, то что следует писать в конструкторе: конструктор по умолчанию?
volvo
Я, кстати, только что заметил ошибку в твоих рассуждениях:
Цитата
Но ведь конструктор же вызвать нельзя, => надо создание извлеч из конструктора
это почему "нельзя"? работай через указатели на классы, тогда ты должен будешь вызывать конструктор (инициализировать указатель через new), и деструктор (при delete указателя)

А то, что ты описал - это методы класса, а никакие не простые и не дружественные функции... Причем в del ты вообще что-то не то делаешь...
программер начинающий
т.е. мне надо написать в ф-ии main: new *T1, *T2; или как, я всё равно не понимаю, и как потом вызывать? Не можешь написать это кодом, применительно к моей проге?
Гость
Цитата(Гость @ 25.12.2006 8:01) *

Это задача из учебника Павловской "Объектно-ориентированное программирование. Практикум", стр 102

Препод мне тоже дал эту задачу, причем сдавать мне ее надо сегодня (именно СЕГОДНЯ!!!! через 15 мниут выезжаю). Я даже не расчитывал седня сдать, но благодаря Tribunal`у, Алене, volvo, а также Яндексу и Опере мои планы резко изменилисьsmile.gif))). Как бы сказал мой препод "Радость моя огромна":)))).

В связи в этим хочу выразить искреннюю благодарность всем перечисленным выше лицам (и программам), в особенности Tribunal, за практически готовый исходник программы про треугольники и прямоугольники.
---------------------------
С уважением
Nicolas


Выложи програмку тут плиз
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.