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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перегрузка оператора =, трабл 
V
    Опции темы
neutrino
Дата 20.10.2009, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Gothic soul
****


Профиль
Группа: Модератор
Сообщений: 3041
Регистрация: 25.3.2002
Где: Верхняя Галилея, Кармиэль

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



Приветствую!

Последний раз с С++ сидел очень давно. Вот настряпал код, на который компилятор начал ругаться:
Код

class A
{
public:
    A operator+(const A& a)
    {
    }

    A& operator=(const A& a)
    {
    }
};

class B : public A
{
public:
    B()
    {
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    B b1, b2;

    b1 = b1 + b2;
}


Цитата

error C2679: binary '=' : no operator found which takes a right-hand operand of type 'A' (or there is no acceptable conversion)    

Я так понимаю, оператор + возвращает объект класса А, а у В нет бинарного оператора = который берет справа объект класса А. Но ведь у предка В (А) есть оператор = который берет справа А, а по скольку объект В является всегда и объектом А, то все должно сработать. Что я не догоняю?

Необходимо, чтобы это все скомпилилось. Пока реализации нет, но это и неважно.


--------------------
The truth comes from within ...

Покойся с миром, Vit 
PM MAIL WWW ICQ Skype GTalk   Вверх
azesmcar
Дата 20.10.2009, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



neutrino

Цитата(Standard)

An assignment operator shall be implemented by a non-static member function with exactly one parameter.
Because a copy assignment operator operator= is implicitly declared for a class if not declared by the
user (12.8), a base class assignment operator is always hidden by the copy assignment operator of the
derived class.



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


depict1
****


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

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



происходит это, потому что объекту производного класса нельзя присваивать объекты базового. Можно наоборот, но тогда произойдёт "срезка" объекта.
Код

struct Base { };
struct Derived : Base { };

Base b;
Derived d;
b = d; // OK (срезка)
d = b; // error


Это сообщение отредактировал(а) zim22 - 20.10.2009, 15:17


--------------------
PM MAIL   Вверх
neutrino
Дата 20.10.2009, 15:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Gothic soul
****


Профиль
Группа: Модератор
Сообщений: 3041
Регистрация: 25.3.2002
Где: Верхняя Галилея, Кармиэль

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



На самом деле, если рассматривать перегрузку оператора, как перегрузку функции, то эти аргументы не катят. Ведь я могу использовать скажем перегруженный оператор = с А для переписывания полей А, а для переписывания полей Б уже использовать оператор = перегруженный в Б. Что-то типа:

Код

class A
{
public:
    A& operator+(const A& a){}
    A& operator=(const A& a){}
}

class B : A
{
public:
    B& operator=(const B& b)
    {
        this = (A)b;
        // Copy here fields of B
    }
}


Но по аналогии с функциями это дело не компилится. Значит мне нужно перегружать в В оператор = который берет как аргумент объект класса А. Но ведь тогда получается совсем лишний и дурацкий оператор в В:
Код

class B : A
{
public:
    B& operator=(const A& a)
    {
        ((A)this) = a;
    }
}


Как правильно разрулить ситуацию???
Цитата(azesmcar @  20.10.2009,  11:39 Найти цитируемый пост)
Because a copy assignment operator operator= is implicitly declared for a class if not declared by the
user (12.8), a base class assignment operator is always hidden by the copy assignment operator of the
derived class.

То есть в потомках ВСЕГДА надо перегружать все операторы =, которые были перегружены в предке??? Что-то какашка какая-то или я опять не понял...

Добавлено через 1 минуту и 24 секунды
Цитата(zim22 @  20.10.2009,  14:16 Найти цитируемый пост)
происходит это, потому что объекту производного класса нельзя присваивать объекты базового. Можно наоборот, но тогда произойдёт "срезка" объекта.

Да, как-то об этом не подумал.


--------------------
The truth comes from within ...

Покойся с миром, Vit 
PM MAIL WWW ICQ Skype GTalk   Вверх
azesmcar
Дата 20.10.2009, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



Цитата(neutrino @  20.10.2009,  15:31 Найти цитируемый пост)
То есть в потомках ВСЕГДА надо перегружать все операторы =, которые были перегружены в предке??? Что-то какашка какая-то или я опять не понял... 

Ну в принципе да. Но это нормально. Представим ситуацию.
Код

class A
{
public:
    A& operator = (int q) {
        this->a = q;
        return *this;
    }
private:
    int a;
};

class B : public A
{
public:
private:
    int b;
};

int main()
{
    B b1;
    b1 = 1; // что ожидается здесь?
}

оператор хоть и написан в классе A, он скрыт в классе B, это логично, потому-что этот оператор НЕ ЯВЛЯЕТСЯ оператором присваивания для класса B, он не присваивает члены класса B, он работает для класса A, вот и прекрасно, пусть продолжает работать smile 

Это сообщение отредактировал(а) azesmcar - 20.10.2009, 15:51
PM   Вверх
neutrino
Дата 20.10.2009, 15:56 (ссылка)  | (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Gothic soul
****


Профиль
Группа: Модератор
Сообщений: 3041
Регистрация: 25.3.2002
Где: Верхняя Галилея, Кармиэль

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



Спасибо за объяснения!

[офтоп]
Вот еще почему Java рулит, так это потому, что там нет перегрузки операторов и подобной хрени. Ожидал от C# того же, но оказалось, что и там такая же какашка. По моему перегрузка операторов только путает больше. Исключением может быть уж очень интенсивное программирование каких-нибудь матриц или комплексных чисел где операторы сократят код. Хотя на моей практике в 6 лет таких примеров не было. ИМХО это лишнее. 
[/офтоп]


--------------------
The truth comes from within ...

Покойся с миром, Vit 
PM MAIL WWW ICQ Skype GTalk   Вверх
maxim1000
Дата 20.10.2009, 16:14 (ссылка) |    (голосов:5) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

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



ещё можно написать внутри B такое:
Код

using A::operator=;

тогда дублирования кода не будет

Это сообщение отредактировал(а) maxim1000 - 20.10.2009, 16:14


--------------------
qqq
PM WWW   Вверх
neutrino
Дата 24.10.2009, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Gothic soul
****


Профиль
Группа: Модератор
Сообщений: 3041
Регистрация: 25.3.2002
Где: Верхняя Галилея, Кармиэль

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



maxim1000, Спасибо, то что надо!


--------------------
The truth comes from within ...

Покойся с миром, Vit 
PM MAIL WWW ICQ Skype GTalk   Вверх
niXman
Дата 24.10.2009, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(neutrino @  20.10.2009,  13:56 Найти цитируемый пост)
По моему перегрузка операторов только путает больше.

Не представляю языка программирования без перегрузки операторов. Это огромное удобство, навязать объекту нужное тебе поведение.

Цитата(neutrino @  20.10.2009,  13:56 Найти цитируемый пост)
Хотя на моей практике в 6 лет таких примеров не было. ИМХО это лишнее.

Было. Просто вы не знали что это можно сделать намного проще, и сократить код.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
neutrino
Дата 25.10.2009, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Gothic soul
****


Профиль
Группа: Модератор
Сообщений: 3041
Регистрация: 25.3.2002
Где: Верхняя Галилея, Кармиэль

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



niXman, 
Цитата(niXman @  24.10.2009,  17:03 Найти цитируемый пост)
Было. Просто вы не знали что это можно сделать намного проще, и сократить код.

Нет. Не было. В основном я разрабатывал инфраструктуру.


--------------------
The truth comes from within ...

Покойся с миром, Vit 
PM MAIL WWW ICQ Skype GTalk   Вверх
neutrino
Дата 26.10.2009, 10:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Gothic soul
****


Профиль
Группа: Модератор
Сообщений: 3041
Регистрация: 25.3.2002
Где: Верхняя Галилея, Кармиэль

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



Цитата(niXman @  24.10.2009,  17:03 Найти цитируемый пост)
и сократить код.

I кстати, как можно сократить код с помощью перегрузки операторов? Ведь все, что можно это:

вместо:
someObject.add(anotherObject);

написать:
someObject += anotherObject;

Может быть, если кто-то интенсивно использует какую-нибудь область математики v программировании, тo ему стоит перегрузить операторы. Например в линейной алгебре может оказаться полезно писать умножение через всеm понятный оператор *, а не функцию multiply. Но поскольку я в основном разрабатывал каждый раз что-то для другой области, то мне не стоилo перегружать операторы.

И вообще интересный факт, действительно почему в Java операторы нельзя перегружать? Почему разработчики этого языка не добавили такую возможность?

Я думаю, что код, который использует перегрузку операторов менее поддерживаемый.


--------------------
The truth comes from within ...

Покойся с миром, Vit 
PM MAIL WWW ICQ Skype GTalk   Вверх
zim22
Дата 26.10.2009, 10:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



Цитата(neutrino @  26.10.2009,  10:11 Найти цитируемый пост)
И вообще интересный факт, действительно почему в Java операторы нельзя перегружать? 

http://stackoverflow.com/questions/77718/j...erator-overload
и ещё миллион ссылок в гугле


--------------------
PM MAIL   Вверх
niXman
Дата 26.10.2009, 10:25 (ссылка)    | (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(neutrino @  26.10.2009,  08:11 Найти цитируемый пост)
почему в Java операторы нельзя перегружать?

В комментарии к твоей репутации UnrealMan ответил.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
zim22
Дата 26.10.2009, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


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

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



 smile 
Цитата(niXman @  26.10.2009,  10:25 Найти цитируемый пост)
В комментарии к твоей репутации UnrealMan ответил.

 smile 


--------------------
PM MAIL   Вверх
Kipter
Дата 26.10.2009, 12:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



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

Если вам приходится наследовать класс с перегруженными операторами и появляется желание не перегружать их в классе-потомке, то следует задуматься а правильно ли вы спроектировали класс-предок и класс потомок =) Что делает такого потомок что для него у вас нет желания перегрузить операторы вновь? Может должно быть наоборот Предок должен быть потомком а потомок предком, или потомок вообще должен быть инкапсулирован в предок и т д

Механику перегрузки операторов придумывали не идиоты, все очень логично если вы понимаете что это не просто функции члены =)

 smile 
Цитата

Вот еще почему Java рулит, так это потому, что там нет перегрузки операторов и подобной хрени.

Знаете, если вы работаете на себя и перегрузка операторов для классов у вас нигде не оговорена в контракте или в соглашении группы разработчиков - то вас С++ НЕ ЗАСТАВЛЯЕТ пользоваться перегрузкой операторов, также как и не заставляет обязательно делать многое другое! (например не заставляет обязательно перехватывать все исключения)
Вы можете также как и в Java создавать функции члены (Add, Summ, Equa или как вы там еще их называете =) ) и пользоваться ими себе на здоровье =)

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

А по поводу Java - очень глупо сказано, не в том месте сравниваете языки =)
Да и сравниванием не рекомендую заниматься для разных задач они =)
и каждый в своей сфере хороши.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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