Почему может оператор-> быть перегруженным вручную?

Не был бы он иметь смысл если p->m был просто синтаксический сахар для (*p).m? По существу, каждый operator-> то, что я когда-либо писал, возможно, было реализовано следующим образом:

Foo::Foo* operator->()
{
    return &**this;
}

Есть ли любой случай, где я хотел бы p->m означать что-то еще, чем (*p).m?

15
задан fredoverflow 30 May 2010 в 12:11
поделиться

5 ответов

оператор -> () имеет странное отличие неявно вызывается несколько раз , в то время как тип возврата позволяет . Самый ясный способ показать это - с помощью кода:

struct X {
    int foo;
};

struct Y {
    X x;
    X* operator->() { return &x; }
};

struct Z {
    Y y;
    Y& operator->() { return y; }
};

Z z;
z->foo = 42;          // Works!  Calls both!

Я вспоминаю случай, когда такое поведение было необходимо, чтобы позволить объекту вести себя как прокси для другого объекта в контексте, подобном умному указателю, хотя я не могу вспомнить Детали. Что я действительно помню, так это то, что я мог добиться того, чтобы поведение работало так, как я предполагал, используя синтаксис a-> b , используя этот странный особый случай; Я не смог найти способ заставить (* a) .b работать аналогичным образом.

Не уверен, что это отвечает на ваш вопрос; на самом деле я говорю: «Хороший вопрос, но он еще более странный!»

18
ответ дан 1 December 2019 в 03:34
поделиться

Одним из вариантов использования может быть создание DSL внутри C ++ в соответствии со строками Boost Karma (хотя, похоже, это не приводит к перегрузке -> в их библиотеке), где вы полностью меняете смысл традиционных операторов C ++. Вопрос о том, хорошая ли это идея, определенно остается предметом обсуждения.

3
ответ дан 1 December 2019 в 03:34
поделиться

Я думаю, что он используется для shared_ptr <> при повышении (например). Это делает их "похожими" на обычные указатели, хотя они и являются специальными указателями (подсчет ссылок afaik).

-1
ответ дан 1 December 2019 в 03:34
поделиться

Обычные указатели предлагают p->m и (*p).m, причем p->m является более распространенным. Если бы вы разрешили перегрузку только одного из них, то это было бы несовместимо с типом по умолчанию. Что касается того, почему бы не позволить компилятору переписать его, простой ответ заключается в том, что иногда вы не хотите, чтобы operator-> возвращал T*, в то время как operator* возвращает T&. Разрешение перегружать их по отдельности позволяет создавать комбинации, о которых вы не всегда можете подумать. Но было бы глупо запрещать это только потому, что в настоящее время мы не можем придумать никаких причин, чтобы изменить это. Например, вы можете иметь класс int128 и перегрузить operator+=, чтобы он означал экспоненциацию вместо этого, если вам так хочется.

1
ответ дан 1 December 2019 в 03:34
поделиться

Вы можете захотеть выполнить некоторые другие операции, например, инкрементирование переменной (подсчет доступа) или даже некоторые проверки безопасности и т.д. С другой стороны, у меня никогда не было необходимости перегружать оператор-> ...

0
ответ дан 1 December 2019 в 03:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: