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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> приоритет перегруженных операторов 
:(
    Опции темы
nerdy_weirdie
  Дата 29.3.2011, 04:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Столкнулся с очень странным поведением компилятора VS2005.
Вместо того чтобы использовать подходящий оператор присваивания, он вызывает оператор приведения к другому типу, и затем вызывает перегруженный оператор присваивания.
Почему он так делает, и как этого избегать. Решение всегда явно задавать тип при вызове оператора присваивания не подходит потому что слишком не надежное - кода много и где-нибудь обязательно да забудется. Надо чтобы компилятор сам выбирал нужный оператор.
Код

class CSock
{ ...
    operator SOCKET ();
    CSock& operator  = (SOCKET p_sockFrom);
    CSock& operator  = (CSock& p_sockFrom); ...
}
CSock FindSocket(){...}
void MainProc()
{
 CSock sock = 0;
 sock = FindSocket(); // здесь происходит странное
}

Казалось бы, будет вызван оператор CSock& operator  = (CSock& p_sockFrom); и всё будет работать как надо, но почему-то в этой строке возвращенный объект сначала преобразуется к типу SOCKET при помощи operator SOCKET (); и затем для присвоения вызывается CSock& operator  = (SOCKET p_sockFrom);. В итоге логика учета референсов не работает. Как научить его ходить в лоток?
PM MAIL   Вверх
borisbn
Дата 29.3.2011, 06:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Не решение, а так... костылёк...
А что если в описании класса поднять "правильный" оператор присваивания вверх, перед "неправильными"?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Earnest
Дата 29.3.2011, 07:26 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Лучше убрать нафик оператор приведения. Это вообще штука опасная, чревата всякими непредсказуемыми поведениями, особенно для активно развивающегося кода.
Лучше замени его явной функцией. И, скорее всего, это константная функция должна быть.
Кроме того, хороший тон требует, чтобы оператор присваивания получал константные ссылку, а не копию и уж тем более не просто ссылку.


--------------------
...
PM   Вверх
borisbn
Дата 29.3.2011, 08:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Earnest @  29.3.2011,  07:26 Найти цитируемый пост)
Кроме того, хороший тон требует, чтобы оператор присваивания получал константные ссылку, а не копию и уж тем более не просто ссылку.

судя по всему, не только хороший тон, но и студия smile проверил. заменил на
CSock& operator  = ( const CSock& p_sockFrom);
стал вызываться этот конструктор


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
bsa
Дата 29.3.2011, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



nerdy_weirdie, функция FindSocket() возвращает так называемое rvalue, т.е. временный объект. По стандарту С++, нельзя такие объекты передавать в качестве параметров функциям, принимающим объекты по неконстантной ссылке. Так как у тебя есть оператор преобразования (что вообще считается дурным тоном, так как может вызывать подобные проблемы) и оператор присваивания принимающий SOCKET, то компилятор их и использует.

По хорошему, достаточно сделать конструктор от (const SOCKET&), чтобы при присваивании объекта типа SOCKET вызвался он, а затем operator=(const CSock&) для полученного объекта:
Код
class CSock
{
    //...
    CSock(); //делает зануление, вместо sock=0
    //CSock(const CSock &sockFrom); //конструктор копирования, ОБЯЗАТЕЛЬНО нужен, если есть выделение ресурсов
    //~CSock(); //деструктор, ОБЯЗАТЕЛЬНО нужен, если есть выделение ресурсов в конструкторах
    CSock(const SOCKET &sockFrom);
    CSock& operator=(const CSock &sockFrom) {
        CSock(sockFrom).swap(*this);
        return *this;
    }
    void swap(CSock &sock);   //сильно упрощает жизнь
    SOCKET toSOCKET() const; //не вызывает неоднозначностей, в отличие от оператора приведения типа
};
CSock FindSocket(){...}
void MainProc()
{
 CSock sock;
 sock = FindSocket();
}

PM   Вверх
nerdy_weirdie
Дата 29.3.2011, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Спасибо, с константной ссылкой работает. Но всё равно такое поведение мне кажется неадекватным.
PM MAIL   Вверх
borisbn
Дата 29.3.2011, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(nerdy_weirdie @  29.3.2011,  17:25 Найти цитируемый пост)
Но всё равно такое поведение мне кажется неадекватным.


Цитата(bsa @  29.3.2011,  10:32 Найти цитируемый пост)
функция FindSocket() возвращает так называемое rvalue, т.е. временный объект. По стандарту С++, нельзя такие объекты передавать в качестве параметров функциям, принимающим объекты по неконстантной ссылке.


я правильно понял, что поведение компилятора по стандарту кажется неадекватным smile
 smile 
Бедная M$. Делает не по стандарту (кстати, довольно часто) - ругают. Делают по стандарту - получите, распишитесь smile

оффтопиковый  smile 
а что ты хотел от класса СНосок ?
 smile 

Это сообщение отредактировал(а) borisbn - 29.3.2011, 17:54


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
kemiisto
  Дата 29.3.2011, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дикий Кот. =^.^=
****
Награды: 1



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

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



Цитата(borisbn @  29.3.2011,  15:52 Найти цитируемый пост)
я правильно понял, что поведение компилятора по стандарту кажется неадекватным

По-моему, у ТС сомнения в адыкватности стандарта. То есть в адыкватности языка.

Сомнения правильные. smile Раунд 100500! Гонг! Поехали!


--------------------
PM MAIL WWW GTalk Jabber   Вверх
borisbn
Дата 29.3.2011, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(kemiisto @  29.3.2011,  17:59 Найти цитируемый пост)
 Раунд 100500! Гонг! Поехали!

поехали.
Апперкот - компилятор Си++ есть на все известные платформы (кроме разве что андроида)
1 : 0


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
kemiisto
Дата 29.3.2011, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дикий Кот. =^.^=
****
Награды: 1



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

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



Цитата(borisbn @  29.3.2011,  19:27 Найти цитируемый пост)
Апперкот - компилятор Си++ есть на все известные платформы (кроме разве что андроида)
1 : 0 

Казалось бы, и причём тут адыкватность? smile 


--------------------
PM MAIL WWW GTalk Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0668 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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