Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей.
Здесь обсуждаются безопасность, программирование, технологии и многое другое.
Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
 |
Жёсткая задачка про ООП в С++ |

14.06.2007, 00:16
|
|
Познающий
Регистрация: 22.10.2005
Сообщений: 37
Провел на форуме: 520745
Репутация:
141
|
|
Жёсткая задачка про ООП в С++
Прелюдия (можно смело пропустить)
Вообщем хочется написать класс полиномов над некоторым типом aType так, чтобы операции были понолстью френд-перегружены, т.е. чтобы работало int==Polynom<int>, int*Polynom<int> и другие приятности.
В не-шаблонном случае это - тривиальнейшая задача. Как только я ввожу шаблоны, aType престаёт приводиться к Polynom, хотя конструктор Polynon<int> имеется. Если выкинуть контекст, и оставить только саму проблему, то получится
Задача
Заставить работать парой волшебных пассов
Код:
#include <iostream>
using namespace std;
template <class aType>
class testClass{
public:
aType data;
testClass(aType c): data(c) {}
bool friend operator==<aType>(testClass<aType>, testClass<aType>);
};
template <class aType>
bool operator==(testClass<aType> a, testClass<aType> b){
return a.data==b.data;
}
int main(){
int a=4;
testClass<int> b(4);
if (a==b) cout << "a equals b\n";
if (b==a) cout << "b equals a\n";
}
В таком состоянии выдает две ошибки:
Код:
no match for `testClass<int> & == int &`
no match for `int & == testClass<int> &`
Если вызывать явные конструкторы Polynom(a)==b, всё работает, но тогда инкапсуляция и всё изящество идёт лесом.
Действительно хоть какое-то решение - делать приведения явно, но внутри класса. Т.е. добавив
Код:
bool friend operator==<aType>(aType a, testClass b<aType>);
bool friend operator==<aType>(testClass a<aType>, aType b);
Ни в одной книге попавшейся мне, включая Строуструпа, этого нет. Но кажется совсем сомнительным, что это невозможно, это ж С++!!! Вообщем, надеюсь прояснить этот вопрос
|
|
|

14.06.2007, 00:59
|
|
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме: 5339610
Репутация:
4360
|
|
Ну ясен пень, ты сравниваешь целое число и объект класса. У тебя же нет оператора их сравнения. Кстати, что за компилер? Обычно такое компилеры кушают, создавая временные объекты.. хотя хз, я точно не знаю
|
|
|

14.06.2007, 11:26
|
|
Познающий
Регистрация: 26.07.2005
Сообщений: 54
Провел на форуме: 47901
Репутация:
46
|
|
По-моему, просто надо реализовать соответствующий оператор копирования, поскольку по умолчанию генерируется такой оператор копирования
Код:
testClass<aType>& testClass<aType>::operator = (const testClass<aType>& hs)
вам для неявного преобразования надо реализовать такой оператор класса, который в качестве аргумента принимает не testClass<aType>& , а аргумент aType &
Код:
testClass<aType>& testClass<aType>::operator = (const aType& hs){
data = hs;
return *this;
};
Последний раз редактировалось Aag; 14.06.2007 в 11:33..
|
|
|

14.06.2007, 12:19
|
|
Познающий
Регистрация: 22.10.2005
Сообщений: 37
Провел на форуме: 520745
Репутация:
141
|
|
2 _Great_
У меня есть функция сравнения двух объектов класса testClass<int> и есть котструктор testClass<int>(int). Так что компилятор может привети оба операнда к типу testClass<int> и сравнить. Более того, если выкинуть все шаблоны и везде заменить aType на int (а testClass<int> b(4) на testClass b(4)), то всё именно так и работает.
Компялятор - gcc (win).
2 Aag
А где здесь копирование? Я же иницаализирую не элементом того же класса, а int-ом...
В любом случае, добавление явного оператора копирования ничего не меняет, те же ошибки
|
|
|

14.06.2007, 23:07
|
|
Познающий
Регистрация: 26.07.2005
Сообщений: 54
Провел на форуме: 47901
Репутация:
46
|
|
Компильнул твой код из начала темы. Ни одной ошибки. Все работает без изменений.
Получил
Код:
a equals b
b equals a
Копилятор gcc 3.3.5 (*nix)
про оператор присваивания я не прав. здесь действительно инициализация идет.
|
|
|

15.06.2007, 01:08
|
|
Познающий
Регистрация: 22.10.2005
Сообщений: 37
Провел на форуме: 520745
Репутация:
141
|
|
Пробовал на:
BSD: gcc version 3.4.2 [FreeBSD] 20040728
Linux: gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
Win: gcc version 2.95.2 19991024 (release)
Win: gcc version 3.4.2 (mingw-special)
И вcе выдают более-менее одну и ту же ошибку.
Это однако ппц какой-то.
Можете привести что точно выводит это компилятор на gcc -v ? Мож там ключи какие хитрые подефолту?
Последний раз редактировалось pch; 15.06.2007 в 01:11..
|
|
|

15.06.2007, 15:36
|
|
Познающий
Регистрация: 26.07.2005
Сообщений: 54
Провел на форуме: 47901
Репутация:
46
|
|
gcc -v: gcc version 3.3.5
Попробывал на mingw 3.4.5 под win действительно не работает.
Но при минимальных изменениях все работает под mingw 3.4.5
Код:
#include <iostream>
template <typename aType>
class testClass{
public:
aType data;
testClass(aType c): data(c) {};
bool friend operator==(testClass<aType> a, testClass<aType> b){return a.data==b.data;} ;
};
int main(){
int a=4;
testClass<int> b(4);
if (a==b) std::cout << "a equals b\n";
if (b==a) std::cout << "b equals a\n";
};
то есть если внести описания друга внутрь класса.
Вот посмотри еще http://en.wikipedia.org/wiki/Barton-Nackman_trick
Последний раз редактировалось Aag; 15.06.2007 в 15:40..
|
|
|

15.06.2007, 17:00
|
|
Познающий
Регистрация: 22.10.2005
Сообщений: 37
Провел на форуме: 520745
Репутация:
141
|
|
Ух-ты. Я просто в Ахуе. Огромный респект!
|
|
|

16.06.2007, 15:36
|
|
Banned
Регистрация: 20.06.2005
Сообщений: 880
Провел на форуме: 4610226
Репутация:
1332
|
|
 а так по-моему много проще:
operator int()
{
return data;
}
|
|
|

16.06.2007, 16:00
|
|
Познающий
Регистрация: 22.10.2005
Сообщений: 37
Провел на форуме: 520745
Репутация:
141
|
|
2 ZaCo
Ну тогда уж не operator int(), а operator aType(), но в любом случае это - не то  . Этот оператор преобразует оба операнда к типу aType (в данном случае - int), и сравнивает их как инты. А если в классе не одно поле (например, рац числа над типом int), то приведение к инту даст лажу (можно приводить в частном случае к флоату, но в общем шаблонном случае непонятно к чему приводить).
Убедиться, что оператор сравнения в классе testClass lдействительно не вызывается просто, достаточно добавить туда cout:
Код:
#include <iostream>
using namespace std;
template <class aType>
class testClass{
public:
aType data;
testClass(aType c): data(c) {}
bool friend operator==<aType>(testClass<aType>, testClass<aType>);
operator aType(){
return data;
}
};
template <class aType>
bool operator==(testClass<aType> a, testClass<aType> b){
cout << "Operator == exucuted\n";
return a.data==b.data;
}
int main(){
int a=4;
testClass<int> b(4);
if (a==b) cout << "a equals b\n";
if (b==a) cout << "b equals a\n";
}
Этот код не выведет фразу "Operator == exucuted" ни разу
|
|
|
|
 |
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|