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

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

Страниц: [1] 2 3 ... 6   Вниз
  Печать  
Автор Тема: Реализация интерфейса[РЕШЕНО]  (Прочитано 46316 раз)
Даниил
Гость
« : Апрель 02, 2012, 10:56 »

Приветствую. Возник вопрос, незнаю где найти ответ - как сделать правильно, подскажите?
Имеется интерфейс:
Код
C++ (Qt)
class Number
{
   /* ... */
public:
   virtual Number& operator +(Number& n) = 0;
   /* ...  */
}
 
class PNumber : public Number
{
  /* ... */
private:
   int acc;
public:
   PNumber& operator +(Number& n);
  /* ... */
}
 

Нужно написать реализацию метода для класса PNumber. Затык случился в момент осознания, что мы передаем в метод тип, которые не знает, о существовании PNumber::acc и соотвественно сложение там выполнить нельзя.
Понимаю, что пример христоматийный, но не могу сам додумать и найти не могу в книжках. Подскажите, где искать?
« Последнее редактирование: Апрель 11, 2012, 21:15 от Даниил » Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #1 : Апрель 02, 2012, 11:18 »

Закастать?
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Даниил
Гость
« Ответ #2 : Апрель 02, 2012, 11:20 »

Закастать?
А это правильно? Или есть стандартное решение из учебника?
Мне тоже такое в голову лезет, но пока я упорно отбиваюсь от такой идеи.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Апрель 02, 2012, 12:09 »

Чтобы Вас не грызла совесть - в книжке такого точно нет. Делать операторы виртуальными нет смысла, т.к. все равно так или иначе придется каститься, причем весьма неудобно. Напр Вы написали

Код
C++ (Qt)
   virtual Number& Number::operator +(Number& n) = 0;
   ...
   PNumber& PNumber::operator +(Number& n);
 
Второй даже не будет виртуальным - ведь тип возвращаемого значения разный. Придется городить такую ахинею
Код
C++ (Qt)
Number& PNumber::operator +(Number& n)
{
PNumber * n2 = dynamic_cast <PNumber *> (n);
if (!n2) assert(0);
// складываем
return *this;
}
 

"Правильный" тот оператор который повторяет привычную логику операции без всяких классов. Разве + меняет операнды? Нет (для этого есть +=). Разве он возвращает по ссылке? Нет, по значению. Зачем же Вы пишете оператор + который не облегчает а наоборот?  
Код
C++ (Qt)
// обычная операция
 int a, b c;
 с = a + b;
 
// теперь все то же но с классами
friend PNumber operator + ( const PNumber & pn1, const PNumber & pn2 );
 
 PNumber a, b c;
 с = a + b;
 
Хотя вероятно все это я пишу напрасно - с полгода назад Вы задавали примерно такой же вопрос  Плачущий
Записан
Даниил
Гость
« Ответ #4 : Апрель 02, 2012, 12:15 »

Хотя вероятно все это я пишу напрасно - с полгода назад Вы задавали примерно такой же вопрос  Плачущий
Курсовики похожие Улыбающийся Только тогда была просто реализация. А теперь нужно написать интерфейс - базовый класс, от него породить 3 класса. Суть:
Код
C++ (Qt)
Nump *n = new PNumb();
Nump *n1 = new PNumb();
n = n + n1;
 
Чтобы используя 1 интерфейс можно было манипулировать разными типами.
P.S. Я помню вашу помощь, и ценю ваше внимание.
« Последнее редактирование: Апрель 02, 2012, 12:45 от Даниил » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Апрель 02, 2012, 13:15 »

Ладно, разжалобили  Улыбающийся  Сделайте так
Код
C++ (Qt)
// базовый класс
class Number {
Number & operator += ( const Number & n1 )  // сам оператор не виртуальный
{
   return DoVirtalInc(n1);  // но вызывает виртуальный метод
}
 
virtual Number & DoVirtalInc( const Number & n1 ) = 0;
};
 
// порожденный класс
class PNumber {
PNumber & operator += ( const PNumber & n1 )  // обычный не виртуальный оператор
{
   acc += n1.acc;  // складываем
   return *this;
}
 
virtual Number & DoVirtalInc( const Number & n1 )
{
  PNumber * pn1 = dynamic_cast <PNumber *> (&n1);
  if (pn1) *this += *pn1;
  return *this;
}
};
 
В принципе ничего особо не выигрываем - и так и так приводиться надо. Но операторы лучше оставить "обычными", другие очень быстро "вынесут моск"
Записан
Даниил
Гость
« Ответ #6 : Апрель 02, 2012, 13:52 »

Я сдаюсь. Посмотрите задание. Надеюсь меня не спалят >_<
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #7 : Апрель 02, 2012, 15:59 »

Обычно операторы сложения, вычитания, умножения и деления делают в виде дружественных функций класса, а не его членами и в этом есть зерно здравого смысла)

Цитировать
Код
C++ (Qt)
Nump *n = new PNumb();
Nump *n1 = new PNumb();
n = n + n1;
 


Это плохая идея. Во-первых n и n1 - это указатели. Формально вы конечно можете их сложить и компилятор даже ничего не скажет) Но в результате получите бред)

Поэтому в любом случае придётся писать делать каст.
Не вижу смысла в базовом (чисто абстрактном) классе объявлять эти операторы, да ещё и виртуальными..   
Записан

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

Arch Linux Plasma 5
Даниил
Гость
« Ответ #8 : Апрель 02, 2012, 16:11 »

Ну да, я там погорячился с указателями - просто хотел передать смысл. А делать операторы сложения, вычитания ... в виде дружественных функций - это нарушение ООП. Так что, ата-та-та.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #9 : Апрель 02, 2012, 16:33 »

Ну да, я там погорячился с указателями - просто хотел передать смысл. А делать операторы сложения, вычитания ... в виде дружественных функций - это нарушение ООП. Так что, ата-та-та.
Где это там нарушение ООП?)

Вариант, когда операторы сложения, вычитания.. пишутся в виде функций, а не членов класса - это более гибкий подход. Он даёт возможность писать более сложные конструкции выражений.
А вариант, когда эти операторы являются членами класса более ограничен в этом плане.

   
 
Записан

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

Arch Linux Plasma 5
Даниил
Гость
« Ответ #10 : Апрель 02, 2012, 16:43 »

Нарушение инкапсуляции идет. Я уже получил звездюлей за такую реализацию. О внутренних деталях класса должен знать только класс. А сторонние функции/классы должны иметь доступ только к методам.
Может быть в вашем случае большая гибкость получается - не спорю. Но типа как - не клёва ^_^  Смеющийся  Смеющийся  Смеющийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Апрель 02, 2012, 16:46 »

идея. Во-первых n и n1 - это указатели. Формально вы конечно можете их сложить и компилятор даже ничего не скажет)
Очень даже скажет (указатель + целое = новый указатель, но не указатель + указатель)

А делать операторы сложения, вычитания ... в виде дружественных функций - это нарушение ООП. Так что, ата-та-та.
Лучше совершенствоваться в языке чем в демагогии.

Я сдаюсь. Посмотрите задание. Надеюсь меня не спалят >_<
С точки зрения ++ такая реализация (как в Вашей методичке) неосуществима.

Код
C++ (Qt)
class TANumber
{
   ...
   virtual TANumber& operator + (TANumber& B) = 0;
 
Это значит что все классы наследующие TANumber должны иметь свои операторы + описанные точно так же как этот.

Код
C++ (Qt)
class TReal : public TANumber
{
   ...
   virtual TReal&  operator + (TANumber& B);
};
 
Тип возвращаемого значения другой - значит это уже другой (еще один) оператор. Компилятор будет вякать пока Вы не объявите так
Код
C++ (Qt)
class TReal : public TANumber
{
   ...
   virtual TNumber &  operator + (TANumber& B);
};
 
Иначе TReal - абстрактный класс и создавать объекты такого типа нельзя

Я уже получил звездюлей за такую реализацию.
Хмм.. ну вообще-то правильно дали (хоть и не за то что надо)  Улыбающийся
Записан
Даниил
Гость
« Ответ #12 : Апрель 02, 2012, 16:53 »

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

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Апрель 02, 2012, 17:08 »

Не слишком полагайтесь на эту методичку. Напр там пишут
Код
C++ (Qt)
virtual bool    operator == (TANumber& B);
 
А правильно так
Код
C++ (Qt)
virtual bool operator == (const TANumber& B) const;
 
Конечно не надо конфликтовать и пытаться чего-то доказывать. Просто молча пишите правильно, за это не убьют
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #14 : Апрель 02, 2012, 17:09 »

Нарушение инкапсуляции идет. Я уже получил звездюлей за такую реализацию. О внутренних деталях класса должен знать только класс. А сторонние функции/классы должны иметь доступ только к методам.
Может быть в вашем случае большая гибкость получается - не спорю. Но типа как - не клёва ^_^  Смеющийся  Смеющийся  Смеющийся

Интересно, почему же тогда во всех серьёзных мат. библиотеках эти операторы (+ - *) делаются в виде дружественных функций?
Вот небольшой пример:
Код
C++ (Qt)
class Number
{
public:
   Number() : _x(0) {}
   Number(int x) : _x(x) {}
   Number &operator+(const Number &x) {
       _x += x._x;
       return *this;
   }
   friend std::ostream& operator<<(std::ostream&, const Number&);
   //friend const Number operator+(const Number&, const Number&);
private:
   int _x;
};
 
std::ostream& operator<<(std::ostream& out, const Number& x) {
   out << x._x;
   return out;
}
 
/*
const Number operator+(const Number&x1, const Number &x2) {
   return Number(x1._x + x2._x);
}
*/

 
Number n1 = 1;
Number n2 = 2;
 
Number n3 = n1+(1+n2);
 
cout << n3 << endl;
 
 
Попробуйте скомпилируйте это, когда оператор сложения - член класса.
А если не получится, закомментируйте его и раскомментируйте вариант, где этот оператор в виде дружественной функции.  
Записан

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

Arch Linux Plasma 5
Страниц: [1] 2 3 ... 6   Вверх
  Печать  
 
Перейти в:  


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