Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как лучше всего оформлять композицию классов? 
:(
    Опции темы
Camphene
Дата 3.11.2015, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 12.12.2008

Репутация: нет
Всего: нет



Добрый день!

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

    class TRange
    {
        int FMin;
        int FMax;
 
    public:
        TRange(){};

        int Min() const { return FMin; };
        int Max() const { return FMax; };

        void setMin(int Value) { FMin = Value; };
        void setMax(int Value) { FMax = Value; };

        bool inRange(int Value) const
        {
            return ( Min() <= Value)&&(Value <= Max() );
        }
    }; // TRange

и некоторый класс, включающий интервал чисел (на самом деле — несколько однотипных интервалов).
Как мне кажется, это должна быть композиция классов.
Но как лучше оформить её в C++, если интервал используется не только внутри этого некоторого класса, но и должен быть доступен извне (посмотреть/поменять)?

1) Если сделать поле-интервал закрытым и описать метод, возвращающий ссылку:
Код

    class TTest
    {
        TRange FRange;
    public:
        TRange& Range() {return FRange;};
    }; 

То будет удобно работать с неконстантными методами FRange, но при попытке вызвать из константного метода объекта TTest константный же метод объекта TRange будет проблема (метод Range() возвращает неконстантную ссылку). 
Код

    bool inAllRanges(int Value) const
    {
       return Range().inRange(Value);    // не работает
    }

(Правда, можно обратиться не к методу Range(), а напрямую к полю FRange, но, когда понадобится сделать не «объект в объекте», а «объект в объекте в ещё более крупном объекте», так уже не получится).

2) Если возвращать константную ссылку, 
Код

    class TTest
    {
        TRange FRange;
    public:
        const TRange& Range() const {return FRange;};
    }; 

проблема будет с неконстантными методами, да и вообще — нелогично (интервалы должно быть возможно вводить через GUI).

3) Оформлять изменение элементов интервала через методы самого класса TTest:
Код

    class TTest
    {
        TRange FRange;
    public:
        const TRange& Range() const {return FRange;};
        void setRangeMin(int Value) { FRange.setMin(Value) };
...
    
    }; 

лень (интервалов не только несколько, но они ещё могут потом уточняться/добавляться/изменяться в процессе разработки).

4) Сделать два метода — константный и неконстантный:
Код

    class TTest
    {
        TRange FRange;
    public:
        TRange& Range() {return FRange;};
        const TRange& constRange() const {return FRange;};
    }; 

боюсь запутаться.

5) Если сделать интервал открытым полем:
Код

    class TTest
    {
    public:
        TRange Range;
    }; 

то вроде бы нарушается принцип инкапсуляции (можно будет нечаянно перезаписать его целиком).

Подскажите, пожалуйста, есть ли какой-нибудь традиционный способ решения таких задач?

Это сообщение отредактировал(а) Camphene - 3.11.2015, 14:32
PM MAIL   Вверх
math64
Дата 3.11.2015, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Я считаю лучший вариант (из перечисленных):
Цитата(Camphene @  3.11.2015,  14:22 Найти цитируемый пост)
4) Сделать два метода — константный и неконстантный:
Код
    
    class TTest
    {
        TRange FRange;
    public:
        TRange& Range() {return FRange;}
        const TRange& constRange() const {return FRange;}
    };
 

Если при изменении Range нужно что-то делать дополнительно, кроме как присвоение нового значения в FRange:
Код

        TRange Range() {return FRange;}
        void setRange(const TRange& range);

Можно сделать, чтобы Range выглядел как свойство, но тут довольно много возиться.

PM   Вверх
Camphene
Дата 3.11.2015, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 12.12.2008

Репутация: нет
Всего: нет



Спасибо!

А из неперечисленных?
Мне многое может быть неизвестно/неочевидно/не придти в голову.

В частности, очень интересно было бы узнать про свойства. 
Мне очень не хватает этой возможности в C++ и хотелось бы знать, как их можно реализовать.
PM MAIL   Вверх
math64
Дата 3.11.2015, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Посмотри, как реализован в std::vector operator[].
PM   Вверх
Camphene
Дата 3.11.2015, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 12.12.2008

Репутация: нет
Всего: нет



Спасибо!

P. S.
Я в совершеннейшем изумлении...
Код

    class TTest
    {
        TRange FRange;
    public:
        TRange& Range() {return FRange;}
        const TRange& Range() const {return FRange;}
    };

собирается и работает, хотя у методов одинаковые имена, явные параметры и класс...

Ещё раз спасибо!

Это сообщение отредактировал(а) Camphene - 3.11.2015, 16:07
PM MAIL   Вверх
xvr
Дата 5.11.2015, 15:24 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Конструкция TRange& Range() {return FRange;} по сути открывает приватную переменную FRange всему внешнему миру, что немногим отличается от примого объявления FRange в public части класса  smile 

Цитата(Camphene @  3.11.2015,  14:22 Найти цитируемый пост)
Но как лучше оформить её в C++, если интервал используется не только внутри этого некоторого класса, но и должен быть доступен извне (посмотреть/поменять)?

Это сильно зависит от семантики самого интервала в классе TTest. Методы класса TTest должны отражать операции над сущностью, которую этот класс представляет, а не выдавать нагора доступ к его внутренней кухне  smile 
PM MAIL   Вверх
math64
Дата 5.11.2015, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Вот здесь обсуждался интересный споcоб реализации свойств:
property в С++
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0730 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.